graphql 0.16.0 → 2.0.15

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.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

Files changed (490) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +5 -0
  3. data/lib/generators/graphql/core.rb +69 -0
  4. data/lib/generators/graphql/enum_generator.rb +27 -0
  5. data/lib/generators/graphql/field_extractor.rb +31 -0
  6. data/lib/generators/graphql/input_generator.rb +50 -0
  7. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  8. data/lib/generators/graphql/install/templates/base_mutation.erb +10 -0
  9. data/lib/generators/graphql/install/templates/mutation_type.erb +12 -0
  10. data/lib/generators/graphql/install_generator.rb +197 -0
  11. data/lib/generators/graphql/interface_generator.rb +27 -0
  12. data/lib/generators/graphql/loader_generator.rb +21 -0
  13. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  15. data/lib/generators/graphql/mutation_generator.rb +30 -0
  16. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  17. data/lib/generators/graphql/object_generator.rb +50 -0
  18. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  19. data/lib/generators/graphql/relay.rb +49 -0
  20. data/lib/generators/graphql/relay_generator.rb +21 -0
  21. data/lib/generators/graphql/scalar_generator.rb +22 -0
  22. data/lib/generators/graphql/templates/base_argument.erb +6 -0
  23. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  24. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  25. data/lib/generators/graphql/templates/base_enum.erb +6 -0
  26. data/lib/generators/graphql/templates/base_field.erb +7 -0
  27. data/lib/generators/graphql/templates/base_input_object.erb +7 -0
  28. data/lib/generators/graphql/templates/base_interface.erb +9 -0
  29. data/lib/generators/graphql/templates/base_object.erb +7 -0
  30. data/lib/generators/graphql/templates/base_scalar.erb +6 -0
  31. data/lib/generators/graphql/templates/base_union.erb +6 -0
  32. data/lib/generators/graphql/templates/enum.erb +11 -0
  33. data/lib/generators/graphql/templates/graphql_controller.erb +52 -0
  34. data/lib/generators/graphql/templates/input.erb +9 -0
  35. data/lib/generators/graphql/templates/interface.erb +10 -0
  36. data/lib/generators/graphql/templates/loader.erb +19 -0
  37. data/lib/generators/graphql/templates/mutation.erb +16 -0
  38. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  40. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  41. data/lib/generators/graphql/templates/node_type.erb +9 -0
  42. data/lib/generators/graphql/templates/object.erb +10 -0
  43. data/lib/generators/graphql/templates/query_type.erb +15 -0
  44. data/lib/generators/graphql/templates/scalar.erb +17 -0
  45. data/lib/generators/graphql/templates/schema.erb +30 -0
  46. data/lib/generators/graphql/templates/union.erb +9 -0
  47. data/lib/generators/graphql/type_generator.rb +135 -0
  48. data/lib/generators/graphql/union_generator.rb +33 -0
  49. data/lib/graphql/analysis/ast/analyzer.rb +84 -0
  50. data/lib/graphql/analysis/ast/field_usage.rb +57 -0
  51. data/lib/graphql/analysis/ast/max_query_complexity.rb +22 -0
  52. data/lib/graphql/analysis/ast/max_query_depth.rb +22 -0
  53. data/lib/graphql/analysis/ast/query_complexity.rb +230 -0
  54. data/lib/graphql/analysis/ast/query_depth.rb +55 -0
  55. data/lib/graphql/analysis/ast/visitor.rb +269 -0
  56. data/lib/graphql/analysis/ast.rb +81 -0
  57. data/lib/graphql/analysis.rb +2 -5
  58. data/lib/graphql/analysis_error.rb +1 -0
  59. data/lib/graphql/backtrace/inspect_result.rb +50 -0
  60. data/lib/graphql/backtrace/table.rb +141 -0
  61. data/lib/graphql/backtrace/traced_error.rb +54 -0
  62. data/lib/graphql/backtrace/tracer.rb +80 -0
  63. data/lib/graphql/backtrace.rb +58 -0
  64. data/lib/graphql/coercion_error.rb +13 -0
  65. data/lib/graphql/dataloader/null_dataloader.rb +24 -0
  66. data/lib/graphql/dataloader/request.rb +19 -0
  67. data/lib/graphql/dataloader/request_all.rb +19 -0
  68. data/lib/graphql/dataloader/source.rb +164 -0
  69. data/lib/graphql/dataloader.rb +311 -0
  70. data/lib/graphql/date_encoding_error.rb +16 -0
  71. data/lib/graphql/deprecation.rb +9 -0
  72. data/lib/graphql/dig.rb +19 -0
  73. data/lib/graphql/execution/directive_checks.rb +37 -0
  74. data/lib/graphql/execution/errors.rb +93 -0
  75. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  76. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  77. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  78. data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
  79. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  80. data/lib/graphql/execution/interpreter/resolve.rb +77 -0
  81. data/lib/graphql/execution/interpreter/runtime.rb +994 -0
  82. data/lib/graphql/execution/interpreter.rb +226 -0
  83. data/lib/graphql/execution/lazy/lazy_method_map.rb +98 -0
  84. data/lib/graphql/execution/lazy.rb +75 -0
  85. data/lib/graphql/execution/lookahead.rb +311 -0
  86. data/lib/graphql/execution/multiplex.rb +45 -0
  87. data/lib/graphql/execution.rb +18 -0
  88. data/lib/graphql/execution_error.rb +34 -1
  89. data/lib/graphql/filter.rb +53 -0
  90. data/lib/graphql/integer_decoding_error.rb +17 -0
  91. data/lib/graphql/integer_encoding_error.rb +36 -0
  92. data/lib/graphql/introspection/base_object.rb +13 -0
  93. data/lib/graphql/introspection/directive_location_enum.rb +12 -5
  94. data/lib/graphql/introspection/directive_type.rb +30 -10
  95. data/lib/graphql/introspection/dynamic_fields.rb +12 -0
  96. data/lib/graphql/introspection/entry_points.rb +22 -0
  97. data/lib/graphql/introspection/enum_value_type.rb +21 -8
  98. data/lib/graphql/introspection/field_type.rb +26 -10
  99. data/lib/graphql/introspection/input_value_type.rb +64 -14
  100. data/lib/graphql/introspection/introspection_query.rb +7 -76
  101. data/lib/graphql/introspection/schema_type.rb +42 -17
  102. data/lib/graphql/introspection/type_kind_enum.rb +11 -5
  103. data/lib/graphql/introspection/type_type.rb +104 -16
  104. data/lib/graphql/introspection.rb +104 -13
  105. data/lib/graphql/invalid_name_error.rb +11 -0
  106. data/lib/graphql/invalid_null_error.rb +36 -8
  107. data/lib/graphql/language/block_string.rb +99 -0
  108. data/lib/graphql/language/cache.rb +37 -0
  109. data/lib/graphql/language/definition_slice.rb +41 -0
  110. data/lib/graphql/language/document_from_schema_definition.rb +335 -0
  111. data/lib/graphql/language/generation.rb +16 -86
  112. data/lib/graphql/language/lexer.rb +1436 -705
  113. data/lib/graphql/language/lexer.rl +172 -64
  114. data/lib/graphql/language/nodes.rb +617 -105
  115. data/lib/graphql/language/parser.rb +1524 -430
  116. data/lib/graphql/language/parser.y +348 -73
  117. data/lib/graphql/language/printer.rb +386 -0
  118. data/lib/graphql/language/sanitized_printer.rb +222 -0
  119. data/lib/graphql/language/token.rb +16 -3
  120. data/lib/graphql/language/visitor.rb +169 -25
  121. data/lib/graphql/language.rb +30 -0
  122. data/lib/graphql/load_application_object_failed_error.rb +22 -0
  123. data/lib/graphql/name_validator.rb +11 -0
  124. data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
  125. data/lib/graphql/pagination/array_connection.rb +79 -0
  126. data/lib/graphql/pagination/connection.rb +253 -0
  127. data/lib/graphql/pagination/connections.rb +135 -0
  128. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  129. data/lib/graphql/pagination/relation_connection.rb +228 -0
  130. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  131. data/lib/graphql/pagination.rb +6 -0
  132. data/lib/graphql/parse_error.rb +24 -0
  133. data/lib/graphql/query/context.rb +266 -12
  134. data/lib/graphql/query/fingerprint.rb +26 -0
  135. data/lib/graphql/query/input_validation_result.rb +34 -7
  136. data/lib/graphql/query/null_context.rb +52 -0
  137. data/lib/graphql/query/result.rb +63 -0
  138. data/lib/graphql/query/validation_pipeline.rb +114 -0
  139. data/lib/graphql/query/variable_validation_error.rb +27 -3
  140. data/lib/graphql/query/variables.rb +75 -24
  141. data/lib/graphql/query.rb +359 -92
  142. data/lib/graphql/railtie.rb +13 -0
  143. data/lib/graphql/rake_task/validate.rb +63 -0
  144. data/lib/graphql/rake_task.rb +146 -0
  145. data/lib/graphql/relay/range_add.rb +52 -0
  146. data/lib/graphql/relay.rb +3 -0
  147. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  148. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  149. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  150. data/lib/graphql/rubocop.rb +4 -0
  151. data/lib/graphql/runtime_type_error.rb +5 -0
  152. data/lib/graphql/schema/addition.rb +245 -0
  153. data/lib/graphql/schema/argument.rb +395 -0
  154. data/lib/graphql/schema/base_64_bp.rb +26 -0
  155. data/lib/graphql/schema/base_64_encoder.rb +21 -0
  156. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +47 -0
  157. data/lib/graphql/schema/build_from_definition/resolve_map.rb +78 -0
  158. data/lib/graphql/schema/build_from_definition.rb +492 -0
  159. data/lib/graphql/schema/built_in_types.rb +12 -0
  160. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  161. data/lib/graphql/schema/directive/feature.rb +66 -0
  162. data/lib/graphql/schema/directive/flagged.rb +57 -0
  163. data/lib/graphql/schema/directive/include.rb +25 -0
  164. data/lib/graphql/schema/directive/one_of.rb +12 -0
  165. data/lib/graphql/schema/directive/skip.rb +25 -0
  166. data/lib/graphql/schema/directive/transform.rb +60 -0
  167. data/lib/graphql/schema/directive.rb +212 -0
  168. data/lib/graphql/schema/enum.rb +176 -0
  169. data/lib/graphql/schema/enum_value.rb +77 -0
  170. data/lib/graphql/schema/field/connection_extension.rb +80 -0
  171. data/lib/graphql/schema/field/scope_extension.rb +22 -0
  172. data/lib/graphql/schema/field.rb +862 -0
  173. data/lib/graphql/schema/field_extension.rb +156 -0
  174. data/lib/graphql/schema/find_inherited_value.rb +36 -0
  175. data/lib/graphql/schema/finder.rb +155 -0
  176. data/lib/graphql/schema/input_object.rb +258 -0
  177. data/lib/graphql/schema/interface.rb +113 -0
  178. data/lib/graphql/schema/introspection_system.rb +164 -0
  179. data/lib/graphql/schema/invalid_type_error.rb +1 -0
  180. data/lib/graphql/schema/late_bound_type.rb +37 -0
  181. data/lib/graphql/schema/list.rb +86 -0
  182. data/lib/graphql/schema/loader.rb +228 -0
  183. data/lib/graphql/schema/member/base_dsl_methods.rb +124 -0
  184. data/lib/graphql/schema/member/build_type.rb +178 -0
  185. data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
  186. data/lib/graphql/schema/member/has_arguments.rb +376 -0
  187. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  188. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  189. data/lib/graphql/schema/member/has_directives.rb +113 -0
  190. data/lib/graphql/schema/member/has_fields.rb +163 -0
  191. data/lib/graphql/schema/member/has_interfaces.rb +88 -0
  192. data/lib/graphql/schema/member/has_path.rb +25 -0
  193. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  194. data/lib/graphql/schema/member/has_validators.rb +31 -0
  195. data/lib/graphql/schema/member/relay_shortcuts.rb +73 -0
  196. data/lib/graphql/schema/member/scoped.rb +21 -0
  197. data/lib/graphql/schema/member/type_system_helpers.rb +38 -0
  198. data/lib/graphql/schema/member/validates_input.rb +33 -0
  199. data/lib/graphql/schema/member.rb +39 -0
  200. data/lib/graphql/schema/mutation.rb +85 -0
  201. data/lib/graphql/schema/non_null.rb +67 -0
  202. data/lib/graphql/schema/null_mask.rb +11 -0
  203. data/lib/graphql/schema/object.rb +117 -0
  204. data/lib/graphql/schema/printer.rb +72 -128
  205. data/lib/graphql/schema/relay_classic_mutation.rb +179 -0
  206. data/lib/graphql/schema/resolver/has_payload_type.rb +106 -0
  207. data/lib/graphql/schema/resolver.rb +402 -0
  208. data/lib/graphql/schema/scalar.rb +68 -0
  209. data/lib/graphql/schema/subscription.rb +148 -0
  210. data/lib/graphql/schema/timeout.rb +123 -0
  211. data/lib/graphql/schema/type_expression.rb +29 -5
  212. data/lib/graphql/schema/type_membership.rb +51 -0
  213. data/lib/graphql/schema/union.rb +81 -0
  214. data/lib/graphql/schema/unique_within_type.rb +34 -0
  215. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  216. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  217. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  218. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  219. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  220. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  221. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  222. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  223. data/lib/graphql/schema/validator.rb +171 -0
  224. data/lib/graphql/schema/warden.rb +413 -0
  225. data/lib/graphql/schema/wrapper.rb +24 -0
  226. data/lib/graphql/schema.rb +1179 -104
  227. data/lib/graphql/static_validation/all_rules.rb +14 -0
  228. data/lib/graphql/static_validation/base_visitor.rb +200 -0
  229. data/lib/graphql/static_validation/definition_dependencies.rb +198 -0
  230. data/lib/graphql/static_validation/error.rb +46 -0
  231. data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
  232. data/lib/graphql/static_validation/literal_validator.rb +113 -22
  233. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +59 -11
  234. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +48 -0
  235. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +31 -0
  236. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
  237. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +62 -8
  238. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +37 -0
  239. data/lib/graphql/static_validation/rules/directives_are_defined.rb +20 -13
  240. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
  241. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +32 -26
  242. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
  243. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +21 -23
  244. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
  245. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +55 -18
  246. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
  247. data/lib/graphql/static_validation/rules/fields_will_merge.rb +390 -70
  248. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +53 -0
  249. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +30 -0
  250. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
  251. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +54 -37
  252. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
  253. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +26 -16
  254. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
  255. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +13 -19
  256. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
  257. data/lib/graphql/static_validation/rules/fragments_are_named.rb +16 -0
  258. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
  259. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +25 -20
  260. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
  261. data/lib/graphql/static_validation/rules/fragments_are_used.rb +22 -33
  262. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
  263. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  264. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  265. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +17 -0
  266. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
  267. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +41 -0
  268. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
  269. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  270. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  271. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +36 -0
  272. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
  273. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  274. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  275. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +22 -21
  276. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
  277. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +59 -0
  278. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
  279. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +17 -0
  280. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
  281. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +56 -0
  282. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
  283. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +36 -18
  284. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
  285. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +24 -0
  286. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
  287. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +103 -39
  288. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
  289. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +22 -14
  290. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
  291. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +92 -70
  292. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
  293. data/lib/graphql/static_validation/type_stack.rb +85 -24
  294. data/lib/graphql/static_validation/validation_context.rb +25 -46
  295. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  296. data/lib/graphql/static_validation/validator.rb +46 -15
  297. data/lib/graphql/static_validation.rb +6 -3
  298. data/lib/graphql/string_encoding_error.rb +20 -0
  299. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +247 -0
  300. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  301. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
  302. data/lib/graphql/subscriptions/event.rb +144 -0
  303. data/lib/graphql/subscriptions/instrumentation.rb +28 -0
  304. data/lib/graphql/subscriptions/serialize.rb +158 -0
  305. data/lib/graphql/subscriptions.rb +306 -0
  306. data/lib/graphql/tracing/active_support_notifications_tracing.rb +21 -0
  307. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  308. data/lib/graphql/tracing/appsignal_tracing.rb +51 -0
  309. data/lib/graphql/tracing/data_dog_tracing.rb +100 -0
  310. data/lib/graphql/tracing/instrumentation_tracing.rb +83 -0
  311. data/lib/graphql/tracing/new_relic_tracing.rb +51 -0
  312. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  313. data/lib/graphql/tracing/platform_tracing.rb +122 -0
  314. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +32 -0
  315. data/lib/graphql/tracing/prometheus_tracing.rb +67 -0
  316. data/lib/graphql/tracing/scout_tracing.rb +54 -0
  317. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  318. data/lib/graphql/tracing.rb +94 -0
  319. data/lib/graphql/type_kinds.rb +50 -22
  320. data/lib/graphql/types/big_int.rb +23 -0
  321. data/lib/graphql/types/boolean.rb +18 -0
  322. data/lib/graphql/types/float.rb +19 -0
  323. data/lib/graphql/types/id.rb +24 -0
  324. data/lib/graphql/types/int.rb +36 -0
  325. data/lib/graphql/types/iso_8601_date.rb +45 -0
  326. data/lib/graphql/types/iso_8601_date_time.rb +76 -0
  327. data/lib/graphql/types/json.rb +25 -0
  328. data/lib/graphql/types/relay/base_connection.rb +49 -0
  329. data/lib/graphql/types/relay/base_edge.rb +29 -0
  330. data/lib/graphql/types/relay/connection_behaviors.rb +154 -0
  331. data/lib/graphql/types/relay/default_relay.rb +21 -0
  332. data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
  333. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  334. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  335. data/lib/graphql/types/relay/node.rb +15 -0
  336. data/lib/graphql/types/relay/node_behaviors.rb +19 -0
  337. data/lib/graphql/types/relay/page_info.rb +11 -0
  338. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  339. data/lib/graphql/types/relay.rb +39 -0
  340. data/lib/graphql/types/string.rb +29 -0
  341. data/lib/graphql/types.rb +11 -0
  342. data/lib/graphql/unauthorized_error.rb +29 -0
  343. data/lib/graphql/unauthorized_field_error.rb +23 -0
  344. data/lib/graphql/unresolved_type_error.rb +35 -0
  345. data/lib/graphql/version.rb +2 -1
  346. data/lib/graphql.rb +86 -41
  347. data/readme.md +15 -101
  348. metadata +394 -279
  349. data/lib/graphql/analysis/analyze_query.rb +0 -73
  350. data/lib/graphql/analysis/max_query_complexity.rb +0 -25
  351. data/lib/graphql/analysis/max_query_depth.rb +0 -25
  352. data/lib/graphql/analysis/query_complexity.rb +0 -122
  353. data/lib/graphql/analysis/query_depth.rb +0 -54
  354. data/lib/graphql/argument.rb +0 -25
  355. data/lib/graphql/base_type.rb +0 -115
  356. data/lib/graphql/boolean_type.rb +0 -9
  357. data/lib/graphql/define/assign_argument.rb +0 -20
  358. data/lib/graphql/define/assign_enum_value.rb +0 -16
  359. data/lib/graphql/define/assign_object_field.rb +0 -21
  360. data/lib/graphql/define/assignment_dictionary.rb +0 -26
  361. data/lib/graphql/define/defined_object_proxy.rb +0 -32
  362. data/lib/graphql/define/instance_definable.rb +0 -79
  363. data/lib/graphql/define/non_null_with_bang.rb +0 -15
  364. data/lib/graphql/define/type_definer.rb +0 -30
  365. data/lib/graphql/define.rb +0 -8
  366. data/lib/graphql/directive/include_directive.rb +0 -10
  367. data/lib/graphql/directive/skip_directive.rb +0 -11
  368. data/lib/graphql/directive.rb +0 -49
  369. data/lib/graphql/enum_type.rb +0 -95
  370. data/lib/graphql/field.rb +0 -131
  371. data/lib/graphql/float_type.rb +0 -5
  372. data/lib/graphql/id_type.rb +0 -12
  373. data/lib/graphql/input_object_type.rb +0 -71
  374. data/lib/graphql/int_type.rb +0 -5
  375. data/lib/graphql/interface_type.rb +0 -38
  376. data/lib/graphql/internal_representation/node.rb +0 -81
  377. data/lib/graphql/internal_representation/rewrite.rb +0 -177
  378. data/lib/graphql/internal_representation.rb +0 -2
  379. data/lib/graphql/introspection/arguments_field.rb +0 -5
  380. data/lib/graphql/introspection/enum_values_field.rb +0 -13
  381. data/lib/graphql/introspection/fields_field.rb +0 -13
  382. data/lib/graphql/introspection/input_fields_field.rb +0 -12
  383. data/lib/graphql/introspection/interfaces_field.rb +0 -5
  384. data/lib/graphql/introspection/of_type_field.rb +0 -6
  385. data/lib/graphql/introspection/possible_types_field.rb +0 -11
  386. data/lib/graphql/introspection/schema_field.rb +0 -15
  387. data/lib/graphql/introspection/type_by_name_field.rb +0 -16
  388. data/lib/graphql/introspection/typename_field.rb +0 -15
  389. data/lib/graphql/list_type.rb +0 -46
  390. data/lib/graphql/non_null_type.rb +0 -43
  391. data/lib/graphql/object_type.rb +0 -93
  392. data/lib/graphql/query/arguments.rb +0 -76
  393. data/lib/graphql/query/directive_resolution.rb +0 -16
  394. data/lib/graphql/query/executor.rb +0 -45
  395. data/lib/graphql/query/literal_input.rb +0 -90
  396. data/lib/graphql/query/serial_execution/execution_context.rb +0 -31
  397. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -82
  398. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -27
  399. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -42
  400. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -107
  401. data/lib/graphql/query/serial_execution.rb +0 -41
  402. data/lib/graphql/query/type_resolver.rb +0 -25
  403. data/lib/graphql/scalar_type.rb +0 -53
  404. data/lib/graphql/schema/catchall_middleware.rb +0 -34
  405. data/lib/graphql/schema/middleware_chain.rb +0 -28
  406. data/lib/graphql/schema/possible_types.rb +0 -34
  407. data/lib/graphql/schema/reduce_types.rb +0 -68
  408. data/lib/graphql/schema/rescue_middleware.rb +0 -53
  409. data/lib/graphql/schema/timeout_middleware.rb +0 -67
  410. data/lib/graphql/schema/type_map.rb +0 -30
  411. data/lib/graphql/schema/validation.rb +0 -164
  412. data/lib/graphql/static_validation/arguments_validator.rb +0 -48
  413. data/lib/graphql/static_validation/message.rb +0 -36
  414. data/lib/graphql/string_type.rb +0 -5
  415. data/lib/graphql/union_type.rb +0 -38
  416. data/spec/graphql/analysis/analyze_query_spec.rb +0 -50
  417. data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -62
  418. data/spec/graphql/analysis/max_query_depth_spec.rb +0 -100
  419. data/spec/graphql/analysis/query_complexity_spec.rb +0 -235
  420. data/spec/graphql/analysis/query_depth_spec.rb +0 -80
  421. data/spec/graphql/argument_spec.rb +0 -20
  422. data/spec/graphql/base_type_spec.rb +0 -24
  423. data/spec/graphql/boolean_type_spec.rb +0 -20
  424. data/spec/graphql/define/instance_definable_spec.rb +0 -55
  425. data/spec/graphql/directive_spec.rb +0 -77
  426. data/spec/graphql/enum_type_spec.rb +0 -31
  427. data/spec/graphql/execution_error_spec.rb +0 -61
  428. data/spec/graphql/field_spec.rb +0 -92
  429. data/spec/graphql/float_type_spec.rb +0 -15
  430. data/spec/graphql/id_type_spec.rb +0 -32
  431. data/spec/graphql/input_object_type_spec.rb +0 -162
  432. data/spec/graphql/int_type_spec.rb +0 -15
  433. data/spec/graphql/interface_type_spec.rb +0 -56
  434. data/spec/graphql/internal_representation/rewrite_spec.rb +0 -120
  435. data/spec/graphql/introspection/directive_type_spec.rb +0 -50
  436. data/spec/graphql/introspection/input_value_type_spec.rb +0 -42
  437. data/spec/graphql/introspection/introspection_query_spec.rb +0 -10
  438. data/spec/graphql/introspection/schema_type_spec.rb +0 -45
  439. data/spec/graphql/introspection/type_type_spec.rb +0 -122
  440. data/spec/graphql/language/generation_spec.rb +0 -42
  441. data/spec/graphql/language/parser_spec.rb +0 -442
  442. data/spec/graphql/language/visitor_spec.rb +0 -49
  443. data/spec/graphql/list_type_spec.rb +0 -32
  444. data/spec/graphql/non_null_type_spec.rb +0 -31
  445. data/spec/graphql/object_type_spec.rb +0 -42
  446. data/spec/graphql/query/arguments_spec.rb +0 -25
  447. data/spec/graphql/query/context_spec.rb +0 -83
  448. data/spec/graphql/query/executor_spec.rb +0 -273
  449. data/spec/graphql/query/serial_execution/execution_context_spec.rb +0 -53
  450. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -66
  451. data/spec/graphql/query/type_resolver_spec.rb +0 -8
  452. data/spec/graphql/query/variables_spec.rb +0 -28
  453. data/spec/graphql/query_spec.rb +0 -363
  454. data/spec/graphql/scalar_type_spec.rb +0 -61
  455. data/spec/graphql/schema/catchall_middleware_spec.rb +0 -32
  456. data/spec/graphql/schema/middleware_chain_spec.rb +0 -42
  457. data/spec/graphql/schema/printer_spec.rb +0 -190
  458. data/spec/graphql/schema/reduce_types_spec.rb +0 -102
  459. data/spec/graphql/schema/rescue_middleware_spec.rb +0 -33
  460. data/spec/graphql/schema/timeout_middleware_spec.rb +0 -180
  461. data/spec/graphql/schema/type_expression_spec.rb +0 -38
  462. data/spec/graphql/schema/validation_spec.rb +0 -219
  463. data/spec/graphql/schema_spec.rb +0 -23
  464. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -63
  465. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -48
  466. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -34
  467. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -39
  468. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -60
  469. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -31
  470. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -48
  471. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -47
  472. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -39
  473. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -44
  474. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -49
  475. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -25
  476. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -42
  477. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -44
  478. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -63
  479. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -37
  480. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -53
  481. data/spec/graphql/static_validation/type_stack_spec.rb +0 -37
  482. data/spec/graphql/static_validation/validator_spec.rb +0 -69
  483. data/spec/graphql/string_type_spec.rb +0 -15
  484. data/spec/graphql/union_type_spec.rb +0 -31
  485. data/spec/spec_helper.rb +0 -18
  486. data/spec/support/dairy_app.rb +0 -309
  487. data/spec/support/dairy_data.rb +0 -23
  488. data/spec/support/minimum_input_object.rb +0 -16
  489. data/spec/support/star_wars_data.rb +0 -71
  490. data/spec/support/star_wars_schema.rb +0 -76
@@ -1,15 +1,64 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  # Expose some query-specific info to field resolve functions.
4
5
  # It delegates `[]` to the hash that's passed to `GraphQL::Query#initialize`.
5
6
  class Context
6
- attr_accessor :execution_strategy
7
+ module SharedMethods
8
+ # Return this value to tell the runtime
9
+ # to exclude this field from the response altogether
10
+ def skip
11
+ GraphQL::Execution::SKIP
12
+ end
7
13
 
8
- # @return [GraphQL::Language::Nodes::Field] The AST node for the currently-executing field
9
- attr_accessor :ast_node
14
+ # Add error at query-level.
15
+ # @param error [GraphQL::ExecutionError] an execution error
16
+ # @return [void]
17
+ def add_error(error)
18
+ if !error.is_a?(ExecutionError)
19
+ raise TypeError, "expected error to be a ExecutionError, but was #{error.class}"
20
+ end
21
+ errors << error
22
+ nil
23
+ end
10
24
 
11
- # @return [GraphQL::InternalRepresentation::Node] The internal representation for this query node
12
- attr_accessor :irep_node
25
+ # @example Print the GraphQL backtrace during field resolution
26
+ # puts ctx.backtrace
27
+ #
28
+ # @return [GraphQL::Backtrace] The backtrace for this point in query execution
29
+ def backtrace
30
+ GraphQL::Backtrace.new(self)
31
+ end
32
+
33
+ def execution_errors
34
+ @execution_errors ||= ExecutionErrors.new(self)
35
+ end
36
+ end
37
+
38
+ class ExecutionErrors
39
+ def initialize(ctx)
40
+ @context = ctx
41
+ end
42
+
43
+ def add(err_or_msg)
44
+ err = case err_or_msg
45
+ when String
46
+ GraphQL::ExecutionError.new(err_or_msg)
47
+ when GraphQL::ExecutionError
48
+ err_or_msg
49
+ else
50
+ raise ArgumentError, "expected String or GraphQL::ExecutionError, not #{err_or_msg.class} (#{err_or_msg.inspect})"
51
+ end
52
+ # This will assign ast_node and path
53
+ @context.add_error(err)
54
+ end
55
+
56
+ alias :>> :add
57
+ alias :push :add
58
+ end
59
+
60
+ include SharedMethods
61
+ extend Forwardable
13
62
 
14
63
  # @return [Array<GraphQL::ExecutionError>] errors returned during execution
15
64
  attr_reader :errors
@@ -20,24 +69,229 @@ module GraphQL
20
69
  # @return [GraphQL::Schema]
21
70
  attr_reader :schema
22
71
 
72
+ # @return [Array<String, Integer>] The current position in the result
73
+ attr_reader :path
74
+
23
75
  # Make a new context which delegates key lookup to `values`
24
76
  # @param query [GraphQL::Query] the query who owns this context
25
77
  # @param values [Hash] A hash of arbitrary values which will be accessible at query-time
26
- def initialize(query:, values:)
78
+ def initialize(query:, schema: query.schema, values:, object:)
27
79
  @query = query
28
- @schema = query.schema
29
- @values = values || {}
80
+ @schema = schema
81
+ @provided_values = values || {}
82
+ @object = object
83
+ # Namespaced storage, where user-provided values are in `nil` namespace:
84
+ @storage = Hash.new { |h, k| h[k] = {} }
85
+ @storage[nil] = @provided_values
30
86
  @errors = []
87
+ @path = []
88
+ @value = nil
89
+ @context = self # for SharedMethods TODO delete sharedmethods
90
+ @scoped_context = ScopedContext.new(self)
91
+ end
92
+
93
+ class ScopedContext
94
+ def initialize(query_context)
95
+ @query_context = query_context
96
+ @path_contexts = {}
97
+ @no_path = [].freeze
98
+ end
99
+
100
+ def merged_context
101
+ merged_ctx = {}
102
+ each_present_path_ctx do |path_ctx|
103
+ merged_ctx = path_ctx.merge(merged_ctx)
104
+ end
105
+ merged_ctx
106
+ end
107
+
108
+ def merge!(hash)
109
+ current_ctx = @path_contexts[current_path] ||= {}
110
+ current_ctx.merge!(hash)
111
+ end
112
+
113
+ def current_path
114
+ @query_context[:current_path] || @no_path
115
+ end
116
+
117
+ def key?(key)
118
+ each_present_path_ctx do |path_ctx|
119
+ if path_ctx.key?(key)
120
+ return true
121
+ end
122
+ end
123
+ false
124
+ end
125
+
126
+ def [](key)
127
+ each_present_path_ctx do |path_ctx|
128
+ if path_ctx.key?(key)
129
+ return path_ctx[key]
130
+ end
131
+ end
132
+ nil
133
+ end
134
+
135
+ def dig(key, *other_keys)
136
+ each_present_path_ctx do |path_ctx|
137
+ if path_ctx.key?(key)
138
+ found_value = path_ctx[key]
139
+ if other_keys.any?
140
+ return found_value.dig(*other_keys)
141
+ else
142
+ return found_value
143
+ end
144
+ end
145
+ end
146
+ nil
147
+ end
148
+
149
+ private
150
+
151
+ # Start at the current location,
152
+ # but look up the tree for previously-assigned scoped values
153
+ def each_present_path_ctx
154
+ search_path = current_path.dup
155
+ if (current_path_ctx = @path_contexts[search_path])
156
+ yield(current_path_ctx)
157
+ end
158
+
159
+ while search_path.size > 0
160
+ search_path.pop # look one level higher
161
+ if (search_path_ctx = @path_contexts[search_path])
162
+ yield(search_path_ctx)
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ # @return [Hash] A hash that will be added verbatim to the result hash, as `"extensions" => { ... }`
169
+ def response_extensions
170
+ namespace(:__query_result_extensions__)
31
171
  end
32
172
 
173
+ def dataloader
174
+ @dataloader ||= self[:dataloader] || (query.multiplex ? query.multiplex.dataloader : schema.dataloader_class.new)
175
+ end
176
+
177
+ # @api private
178
+ attr_writer :interpreter
179
+
180
+ # @api private
181
+ attr_writer :value
182
+
183
+ # @api private
184
+ attr_reader :scoped_context
185
+
186
+ def []=(key, value)
187
+ @provided_values[key] = value
188
+ end
189
+
190
+ def_delegators :@query, :trace, :interpreter?
191
+
192
+ RUNTIME_METADATA_KEYS = Set.new([:current_object, :current_arguments, :current_field, :current_path])
193
+ # @!method []=(key, value)
194
+ # Reassign `key` to the hash passed to {Schema#execute} as `context:`
195
+
33
196
  # Lookup `key` from the hash passed to {Schema#execute} as `context:`
34
197
  def [](key)
35
- @values[key]
198
+ if RUNTIME_METADATA_KEYS.include?(key)
199
+ thread_info = Thread.current[:__graphql_runtime_info]
200
+ thread_info && thread_info[key]
201
+ elsif @scoped_context.key?(key)
202
+ @scoped_context[key]
203
+ else
204
+ @provided_values[key]
205
+ end
36
206
  end
37
207
 
38
- # Reassign `key` to the hash passed to {Schema#execute} as `context:`
39
- def []=(key, value)
40
- @values[key] = value
208
+ def delete(key)
209
+ if @scoped_context.key?(key)
210
+ @scoped_context.delete(key)
211
+ else
212
+ @provided_values.delete(key)
213
+ end
214
+ end
215
+
216
+ UNSPECIFIED_FETCH_DEFAULT = Object.new
217
+
218
+ def fetch(key, default = UNSPECIFIED_FETCH_DEFAULT)
219
+ if RUNTIME_METADATA_KEYS.include?(key)
220
+ (thread_info = Thread.current[:__graphql_runtime_info]) &&
221
+ thread_info[key]
222
+ elsif @scoped_context.key?(key)
223
+ scoped_context[key]
224
+ elsif @provided_values.key?(key)
225
+ @provided_values[key]
226
+ elsif default != UNSPECIFIED_FETCH_DEFAULT
227
+ default
228
+ elsif block_given?
229
+ yield(self, key)
230
+ else
231
+ raise KeyError.new(key: key)
232
+ end
233
+ end
234
+
235
+ def dig(key, *other_keys)
236
+ if RUNTIME_METADATA_KEYS.include?(key)
237
+ (thread_info = Thread.current[:__graphql_runtime_info]).key?(key) &&
238
+ thread_info.dig(key)
239
+ elsif @scoped_context.key?(key)
240
+ @scoped_context.dig(key, *other_keys)
241
+ else
242
+ @provided_values.dig(key, *other_keys)
243
+ end
244
+ end
245
+
246
+ def to_h
247
+ if (current_scoped_context = @scoped_context.merged_context)
248
+ @provided_values.merge(current_scoped_context)
249
+ else
250
+ @provided_values
251
+ end
252
+ end
253
+
254
+ alias :to_hash :to_h
255
+
256
+ def key?(key)
257
+ @scoped_context.key?(key) || @provided_values.key?(key)
258
+ end
259
+
260
+ # @return [GraphQL::Schema::Warden]
261
+ def warden
262
+ @warden ||= (@query && @query.warden)
263
+ end
264
+
265
+ # @api private
266
+ attr_writer :warden
267
+
268
+ # Get an isolated hash for `ns`. Doesn't affect user-provided storage.
269
+ # @param ns [Object] a usage-specific namespace identifier
270
+ # @return [Hash] namespaced storage
271
+ def namespace(ns)
272
+ if ns == :interpreter
273
+ self
274
+ else
275
+ @storage[ns]
276
+ end
277
+ end
278
+
279
+ # @return [Boolean] true if this namespace was accessed before
280
+ def namespace?(ns)
281
+ @storage.key?(ns)
282
+ end
283
+
284
+ def inspect
285
+ "#<Query::Context ...>"
286
+ end
287
+
288
+ def scoped_merge!(hash)
289
+ @scoped_context.merge!(hash)
290
+ end
291
+
292
+ def scoped_set!(key, value)
293
+ scoped_merge!(key => value)
294
+ nil
41
295
  end
42
296
  end
43
297
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest/sha2'
4
+
5
+ module GraphQL
6
+ class Query
7
+ # @api private
8
+ # @see Query#query_fingerprint
9
+ # @see Query#variables_fingerprint
10
+ # @see Query#fingerprint
11
+ module Fingerprint
12
+ # Make an obfuscated hash of the given string (either a query string or variables JSON)
13
+ # @param string [String]
14
+ # @return [String] A normalized, opaque hash
15
+ def self.generate(input_str)
16
+ # Implemented to be:
17
+ # - Short (and uniform) length
18
+ # - Stable
19
+ # - Irreversibly Opaque (don't want to leak variable values)
20
+ # - URL-friendly
21
+ bytes = Digest::SHA256.digest(input_str)
22
+ Base64.urlsafe_encode64(bytes)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,25 +1,52 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  class InputValidationResult
4
5
  attr_accessor :problems
5
6
 
7
+ def self.from_problem(explanation, path = nil, extensions: nil, message: nil)
8
+ result = self.new
9
+ result.add_problem(explanation, path, extensions: extensions, message: message)
10
+ result
11
+ end
12
+
13
+ def initialize(valid: true, problems: nil)
14
+ @valid = valid
15
+ @problems = problems
16
+ end
17
+
6
18
  def valid?
7
- @problems.nil?
19
+ @valid
8
20
  end
9
21
 
10
- def add_problem(explanation, path = nil)
22
+ def add_problem(explanation, path = nil, extensions: nil, message: nil)
11
23
  @problems ||= []
12
- @problems.push({ "path" => path || [], "explanation" => explanation })
24
+ @valid = false
25
+ problem = { "path" => path || [], "explanation" => explanation }
26
+ if extensions
27
+ problem["extensions"] = extensions
28
+ end
29
+ if message
30
+ problem["message"] = message
31
+ end
32
+ @problems.push(problem)
13
33
  end
14
34
 
15
35
  def merge_result!(path, inner_result)
16
- return if inner_result.valid?
36
+ return if inner_result.nil? || inner_result.valid?
17
37
 
18
- inner_result.problems.each do |p|
19
- item_path = [path, *p["path"]]
20
- add_problem(p["explanation"], item_path)
38
+ if inner_result.problems
39
+ inner_result.problems.each do |p|
40
+ item_path = [path, *p["path"]]
41
+ add_problem(p["explanation"], item_path, message: p["message"], extensions: p["extensions"])
42
+ end
21
43
  end
44
+ # It could have been explicitly set on inner_result (if it had no problems)
45
+ @valid = false
22
46
  end
47
+
48
+ VALID = self.new
49
+ VALID.freeze
23
50
  end
24
51
  end
25
52
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Query
4
+ # This object can be `ctx` in places where there is no query
5
+ class NullContext
6
+ class NullWarden < GraphQL::Schema::Warden
7
+ def visible_field?(field, ctx); true; end
8
+ def visible_argument?(arg, ctx); true; end
9
+ def visible_type?(type, ctx); true; end
10
+ def visible_enum_value?(ev, ctx); true; end
11
+ def visible_type_membership?(tm, ctx); true; end
12
+ end
13
+
14
+ class NullQuery
15
+ end
16
+
17
+ class NullSchema < GraphQL::Schema
18
+ end
19
+
20
+ attr_reader :schema, :query, :warden, :dataloader
21
+
22
+ def initialize
23
+ @query = NullQuery.new
24
+ @dataloader = GraphQL::Dataloader::NullDataloader.new
25
+ @schema = NullSchema
26
+ @warden = NullWarden.new(
27
+ GraphQL::Filter.new,
28
+ context: self,
29
+ schema: @schema,
30
+ )
31
+ end
32
+
33
+ def [](key); end
34
+
35
+ def interpreter?
36
+ true
37
+ end
38
+
39
+ class << self
40
+ extend Forwardable
41
+
42
+ def [](key); end
43
+
44
+ def instance
45
+ @instance ||= self.new
46
+ end
47
+
48
+ def_delegators :instance, :query, :warden, :schema, :interpreter?, :dataloader
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Query
5
+ # A result from {Schema#execute}.
6
+ # It provides the requested data and
7
+ # access to the {Query} and {Query::Context}.
8
+ class Result
9
+ extend Forwardable
10
+
11
+ def initialize(query:, values:)
12
+ @query = query
13
+ @to_h = values
14
+ end
15
+
16
+ # @return [GraphQL::Query] The query that was executed
17
+ attr_reader :query
18
+
19
+ # @return [Hash] The resulting hash of "data" and/or "errors"
20
+ attr_reader :to_h
21
+
22
+ def_delegators :@query, :context, :mutation?, :query?, :subscription?
23
+
24
+ def_delegators :@to_h, :[], :keys, :values, :to_json, :as_json
25
+
26
+ # Delegate any hash-like method to the underlying hash.
27
+ def method_missing(method_name, *args, &block)
28
+ if @to_h.respond_to?(method_name)
29
+ @to_h.public_send(method_name, *args, &block)
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ def respond_to_missing?(method_name, include_private = false)
36
+ @to_h.respond_to?(method_name) || super
37
+ end
38
+
39
+ def inspect
40
+ "#<GraphQL::Query::Result @query=... @to_h=#{@to_h}>"
41
+ end
42
+
43
+ # A result is equal to another object when:
44
+ #
45
+ # - The other object is a Hash whose value matches `result.to_h`
46
+ # - The other object is a Result whose value matches `result.to_h`
47
+ #
48
+ # (The query is ignored for comparing result equality.)
49
+ #
50
+ # @return [Boolean]
51
+ def ==(other)
52
+ case other
53
+ when Hash
54
+ @to_h == other
55
+ when Query::Result
56
+ @to_h == other.to_h
57
+ else
58
+ super
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Query
4
+ # Contain the validation pipeline and expose the results.
5
+ #
6
+ # 0. Checks in {Query#initialize}:
7
+ # - Rescue a ParseError, halt if there is one
8
+ # - Check for selected operation, halt if not found
9
+ # 1. Validate the AST, halt if errors
10
+ # 2. Validate the variables, halt if errors
11
+ # 3. Run query analyzers, halt if errors
12
+ #
13
+ # {#valid?} is false if any of the above checks halted the pipeline.
14
+ #
15
+ # @api private
16
+ class ValidationPipeline
17
+ attr_reader :max_depth, :max_complexity
18
+
19
+ def initialize(query:, parse_error:, operation_name_error:, max_depth:, max_complexity:)
20
+ @validation_errors = []
21
+ @parse_error = parse_error
22
+ @operation_name_error = operation_name_error
23
+ @query = query
24
+ @schema = query.schema
25
+ @max_depth = max_depth
26
+ @max_complexity = max_complexity
27
+
28
+ @has_validated = false
29
+ end
30
+
31
+ # @return [Boolean] does this query have errors that should prevent it from running?
32
+ def valid?
33
+ ensure_has_validated
34
+ @valid
35
+ end
36
+
37
+ # @return [Array<GraphQL::StaticValidation::Error, GraphQL::Query::VariableValidationError>] Static validation errors for the query string
38
+ def validation_errors
39
+ ensure_has_validated
40
+ @validation_errors
41
+ end
42
+
43
+ def analyzers
44
+ ensure_has_validated
45
+ @query_analyzers
46
+ end
47
+
48
+ def has_validated?
49
+ @has_validated == true
50
+ end
51
+
52
+ private
53
+
54
+ # If the pipeline wasn't run yet, run it.
55
+ # If it was already run, do nothing.
56
+ def ensure_has_validated
57
+ return if @has_validated
58
+ @has_validated = true
59
+
60
+ if @parse_error
61
+ # This is kind of crazy: we push the parse error into `ctx`
62
+ # in `def self.parse_error` by default so that users can _opt out_ by redefining that hook.
63
+ # That means we can't _re-add_ the error here (otherwise we'd either
64
+ # add it twice _or_ override the user's choice to not add it).
65
+ # So we just have to know that it was invalid and go from there.
66
+ @valid = false
67
+ return
68
+ elsif @operation_name_error
69
+ @validation_errors << @operation_name_error
70
+ else
71
+ validation_result = @schema.static_validator.validate(@query, validate: @query.validate, timeout: @schema.validate_timeout, max_errors: @schema.validate_max_errors)
72
+ @validation_errors.concat(validation_result[:errors])
73
+
74
+ if @validation_errors.empty?
75
+ @validation_errors.concat(@query.variables.errors)
76
+ end
77
+
78
+ if @validation_errors.empty?
79
+ @query_analyzers = build_analyzers(
80
+ @schema,
81
+ @max_depth,
82
+ @max_complexity
83
+ )
84
+ end
85
+ end
86
+
87
+ @valid = @validation_errors.empty?
88
+ rescue SystemStackError => err
89
+ @valid = false
90
+ @schema.query_stack_error(@query, err)
91
+ end
92
+
93
+ # If there are max_* values, add them,
94
+ # otherwise reuse the schema's list of analyzers.
95
+ def build_analyzers(schema, max_depth, max_complexity)
96
+ qa = schema.query_analyzers.dup
97
+
98
+ if max_depth || max_complexity
99
+ # Depending on the analysis engine, we must use different analyzers
100
+ # remove this once everything has switched over to AST analyzers
101
+ if max_depth
102
+ qa << GraphQL::Analysis::AST::MaxQueryDepth
103
+ end
104
+ if max_complexity
105
+ qa << GraphQL::Analysis::AST::MaxQueryComplexity
106
+ end
107
+ qa
108
+ else
109
+ qa
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -1,19 +1,43 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  class VariableValidationError < GraphQL::ExecutionError
4
5
  attr_accessor :value, :validation_result
5
6
 
6
- def initialize(variable_ast, type, value, validation_result)
7
+ def initialize(variable_ast, type, value, validation_result, msg: nil)
7
8
  @value = value
8
9
  @validation_result = validation_result
9
10
 
10
- msg = "Variable #{variable_ast.name} of type #{type} was provided invalid value"
11
+ msg ||= "Variable $#{variable_ast.name} of type #{type.to_type_signature} was provided invalid value"
12
+
13
+ if problem_fields.any?
14
+ msg += " for #{problem_fields.join(", ")}"
15
+ end
16
+
11
17
  super(msg)
12
18
  self.ast_node = variable_ast
13
19
  end
14
20
 
15
21
  def to_h
16
- super.merge({ "value" => value, "problems" => validation_result.problems })
22
+ # It is possible there are other extension items in this error, so handle
23
+ # a one level deep merge explicitly. However beyond that only show the
24
+ # latest value and problems.
25
+ super.merge({ "extensions" => { "value" => value, "problems" => validation_result.problems }}) do |key, oldValue, newValue|
26
+ if oldValue.respond_to?(:merge)
27
+ oldValue.merge(newValue)
28
+ else
29
+ newValue
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def problem_fields
37
+ @problem_fields ||= @validation_result
38
+ .problems
39
+ .reject { |problem| problem["path"].empty? }
40
+ .map { |problem| "#{problem['path'].join('.')} (#{problem['explanation']})" }
17
41
  end
18
42
  end
19
43
  end