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,40 +1,91 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  class Query
3
4
  # Read-only access to query variables, applying default values if needed.
4
5
  class Variables
5
- def initialize(schema, ast_variables, provided_variables)
6
- @schema = schema
7
- @provided_variables = provided_variables
6
+ extend Forwardable
7
+
8
+ # @return [Array<GraphQL::Query::VariableValidationError>] Any errors encountered when parsing the provided variables and literal values
9
+ attr_reader :errors
10
+
11
+ attr_reader :context
12
+
13
+ def initialize(ctx, ast_variables, provided_variables)
14
+ schema = ctx.schema
15
+ @context = ctx
16
+
17
+ @provided_variables = deep_stringify(provided_variables)
18
+ @errors = []
8
19
  @storage = ast_variables.each_with_object({}) do |ast_variable, memo|
9
- variable_name = ast_variable.name
10
- memo[variable_name] = get_graphql_value(ast_variable)
20
+ if schema.validate_max_errors && schema.validate_max_errors <= @errors.count
21
+ add_max_errors_reached_message
22
+ break
23
+ end
24
+ # Find the right value for this variable:
25
+ # - First, use the value provided at runtime
26
+ # - Then, fall back to the default value from the query string
27
+ # If it's still nil, raise an error if it's required.
28
+ variable_type = schema.type_from_ast(ast_variable.type, context: ctx)
29
+ if variable_type.nil?
30
+ # Pass -- it will get handled by a validator
31
+ else
32
+ variable_name = ast_variable.name
33
+ default_value = ast_variable.default_value
34
+ provided_value = @provided_variables[variable_name]
35
+ value_was_provided = @provided_variables.key?(variable_name)
36
+ max_errors = schema.validate_max_errors - @errors.count if schema.validate_max_errors
37
+ begin
38
+ validation_result = variable_type.validate_input(provided_value, ctx, max_errors: max_errors)
39
+ if validation_result.valid?
40
+ if value_was_provided
41
+ # Add the variable if a value was provided
42
+ memo[variable_name] = provided_value
43
+ elsif default_value != nil
44
+ memo[variable_name] = if default_value.is_a?(Language::Nodes::NullValue)
45
+ nil
46
+ else
47
+ default_value
48
+ end
49
+ end
50
+ end
51
+ rescue GraphQL::ExecutionError => ex
52
+ # TODO: This should really include the path to the problematic node in the variable value
53
+ # like InputValidationResults generated by validate_non_null_input but unfortunately we don't
54
+ # have this information available in the coerce_input call chain. Note this path is the path
55
+ # that appears under errors.extensions.problems.path and NOT the result path under errors.path.
56
+ validation_result = GraphQL::Query::InputValidationResult.from_problem(ex.message)
57
+ end
58
+
59
+ if !validation_result.valid?
60
+ @errors << GraphQL::Query::VariableValidationError.new(ast_variable, variable_type, provided_value, validation_result)
61
+ end
62
+ end
11
63
  end
12
64
  end
13
65
 
14
- def [](key)
15
- @storage.fetch(key)
16
- end
66
+ def_delegators :@storage, :length, :key?, :[], :fetch, :to_h
17
67
 
18
68
  private
19
69
 
20
- # Find the right value for this variable:
21
- # - First, use the value provided at runtime
22
- # - Then, fall back to the default value from the query string
23
- # If it's still nil, raise an error if it's required.
24
- def get_graphql_value(ast_variable)
25
- variable_type = @schema.type_from_ast(ast_variable.type)
26
- variable_name = ast_variable.name
27
- default_value = ast_variable.default_value
28
- provided_value = @provided_variables[variable_name]
29
-
30
- validation_result = variable_type.validate_input(provided_value)
31
- if !validation_result.valid?
32
- raise GraphQL::Query::VariableValidationError.new(ast_variable, variable_type, provided_value, validation_result)
33
- elsif provided_value.nil?
34
- GraphQL::Query::LiteralInput.coerce(variable_type, default_value, {})
70
+ def deep_stringify(val)
71
+ case val
72
+ when Array
73
+ val.map { |v| deep_stringify(v) }
74
+ when Hash
75
+ new_val = {}
76
+ val.each do |k, v|
77
+ new_val[k.to_s] = deep_stringify(v)
78
+ end
79
+ new_val
35
80
  else
36
- variable_type.coerce_input(provided_value)
81
+ val
37
82
  end
83
+ end
84
+
85
+ def add_max_errors_reached_message
86
+ message = "Too many errors processing variables, max validation error limit reached. Execution aborted"
87
+ validation_result = GraphQL::Query::InputValidationResult.from_problem(message)
88
+ errors << GraphQL::Query::VariableValidationError.new(nil, nil, nil, validation_result, msg: message)
38
89
  end
39
90
  end
40
91
  end
data/lib/graphql/query.rb CHANGED
@@ -1,163 +1,430 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/query/context"
3
+ require "graphql/query/fingerprint"
4
+ require "graphql/query/null_context"
5
+ require "graphql/query/result"
6
+ require "graphql/query/variables"
7
+ require "graphql/query/input_validation_result"
8
+ require "graphql/query/variable_validation_error"
9
+ require "graphql/query/validation_pipeline"
10
+
1
11
  module GraphQL
2
12
  # A combination of query string and {Schema} instance which can be reduced to a {#result}.
3
13
  class Query
14
+ include Tracing::Traceable
15
+ extend Forwardable
16
+
4
17
  class OperationNameMissingError < GraphQL::ExecutionError
5
- def initialize(names)
6
- msg = "You must provide an operation name from: #{names.join(", ")}"
18
+ def initialize(name)
19
+ msg = if name.nil?
20
+ %|An operation name is required|
21
+ else
22
+ %|No operation named "#{name}"|
23
+ end
7
24
  super(msg)
8
25
  end
9
26
  end
10
27
 
11
- attr_reader :schema, :document, :context, :fragments, :operations, :root_value, :max_depth, :query_string
28
+ attr_reader :schema, :context, :provided_variables
29
+
30
+ # The value for root types
31
+ attr_accessor :root_value
32
+
33
+ # @return [nil, String] The operation name provided by client or the one inferred from the document. Used to determine which operation to run.
34
+ attr_accessor :operation_name
35
+
36
+ # @return [Boolean] if false, static validation is skipped (execution behavior for invalid queries is undefined)
37
+ attr_reader :validate
38
+
39
+ # @param new_validate [Boolean] if false, static validation is skipped. This can't be reasssigned after validation.
40
+ def validate=(new_validate)
41
+ if defined?(@validation_pipeline) && @validation_pipeline && @validation_pipeline.has_validated?
42
+ raise ArgumentError, "Can't reassign Query#validate= after validation has run, remove this assignment."
43
+ else
44
+ @validate = new_validate
45
+ end
46
+ end
47
+
48
+ attr_writer :query_string
49
+
50
+ # @return [GraphQL::Language::Nodes::Document]
51
+ def document
52
+ # It's ok if this hasn't been assigned yet
53
+ if @query_string || @document
54
+ with_prepared_ast { @document }
55
+ else
56
+ nil
57
+ end
58
+ end
59
+
60
+ def inspect
61
+ "query ..."
62
+ end
63
+
64
+ # @return [String, nil] The name of the operation to run (may be inferred)
65
+ def selected_operation_name
66
+ return nil unless selected_operation
67
+ selected_operation.name
68
+ end
69
+
70
+ # @return [String, nil] the triggered event, if this query is a subscription update
71
+ attr_reader :subscription_topic
72
+
73
+ attr_reader :tracers
12
74
 
13
75
  # Prepare query `query_string` on `schema`
14
76
  # @param schema [GraphQL::Schema]
15
77
  # @param query_string [String]
16
78
  # @param context [#[]] an arbitrary hash of values which you can access in {GraphQL::Field#resolve}
17
79
  # @param variables [Hash] values for `$variables` in the query
18
- # @param validate [Boolean] if true, `query_string` will be validated with {StaticValidation::Validator}
19
80
  # @param operation_name [String] if the query string contains many operations, this is the one which should be executed
20
81
  # @param root_value [Object] the object used to resolve fields on the root type
21
82
  # @param max_depth [Numeric] the maximum number of nested selections allowed for this query (falls back to schema-level value)
22
83
  # @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
23
- def initialize(schema, query_string = nil, document: nil, context: nil, variables: {}, validate: true, operation_name: nil, root_value: nil, max_depth: nil, max_complexity: nil)
24
- fail ArgumentError, "a query string or document is required" unless query_string || document
25
-
84
+ # @param except [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns truthy
85
+ # @param only [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns false
86
+ def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, except: nil, only: nil, warden: nil)
87
+ # Even if `variables: nil` is passed, use an empty hash for simpler logic
88
+ variables ||= {}
26
89
  @schema = schema
27
- @max_depth = max_depth || schema.max_depth
28
- @max_complexity = max_complexity || schema.max_complexity
29
- @query_analyzers = schema.query_analyzers.dup
30
- if @max_depth
31
- @query_analyzers << GraphQL::Analysis::MaxQueryDepth.new(@max_depth)
32
- end
33
- if @max_complexity
34
- @query_analyzers << GraphQL::Analysis::MaxQueryComplexity.new(@max_complexity)
35
- end
36
- @context = Context.new(query: self, values: context)
90
+ @filter = schema.default_filter.merge(except: except, only: only)
91
+ @context = schema.context_class.new(query: self, object: root_value, values: context)
92
+ @warden = warden
93
+ @subscription_topic = subscription_topic
37
94
  @root_value = root_value
95
+ @fragments = nil
96
+ @operations = nil
38
97
  @validate = validate
39
- @operation_name = operation_name
40
- @fragments = {}
41
- @operations = {}
42
- @provided_variables = variables
43
- @query_string = query_string
44
-
45
- @document = document || GraphQL.parse(query_string)
46
- @document.definitions.each do |part|
47
- if part.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
48
- @fragments[part.name] = part
49
- elsif part.is_a?(GraphQL::Language::Nodes::OperationDefinition)
50
- @operations[part.name] = part
98
+ @tracers = schema.tracers + (context ? context.fetch(:tracers, []) : [])
99
+ # Support `ctx[:backtrace] = true` for wrapping backtraces
100
+ if context && context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
101
+ @tracers << GraphQL::Backtrace::Tracer
102
+ end
103
+
104
+ @analysis_errors = []
105
+ if variables.is_a?(String)
106
+ raise ArgumentError, "Query variables should be a Hash, not a String. Try JSON.parse to prepare variables."
107
+ else
108
+ @provided_variables = variables || {}
109
+ end
110
+
111
+ @query_string = query_string || query
112
+ @document = document
113
+
114
+ if @query_string && @document
115
+ raise ArgumentError, "Query should only be provided a query string or a document, not both."
116
+ end
117
+
118
+ if @query_string && !@query_string.is_a?(String)
119
+ raise ArgumentError, "Query string argument should be a String, got #{@query_string.class.name} instead."
120
+ end
121
+
122
+ # A two-layer cache of type resolution:
123
+ # { abstract_type => { value => resolved_type } }
124
+ @resolved_types_cache = Hash.new do |h1, k1|
125
+ h1[k1] = Hash.new do |h2, k2|
126
+ h2[k2] = @schema.resolve_type(k1, k2, @context)
51
127
  end
52
128
  end
53
129
 
54
- @arguments_cache = {}
130
+ # Trying to execute a document
131
+ # with no operations returns an empty hash
132
+ @ast_variables = []
133
+ @mutation = false
134
+ @operation_name = operation_name
135
+ @prepared_ast = false
136
+ @validation_pipeline = nil
137
+ @max_depth = max_depth
138
+ @max_complexity = max_complexity
139
+
140
+ @result_values = nil
141
+ @executed = false
142
+
143
+ # TODO add a general way to define schema-level filters
144
+ if @schema.respond_to?(:visible?)
145
+ merge_filters(only: @schema.method(:visible?))
146
+ end
147
+ end
148
+
149
+ # If a document was provided to `GraphQL::Schema#execute` instead of the raw query string, we will need to get it from the document
150
+ def query_string
151
+ @query_string ||= (document ? document.to_query_string : nil)
152
+ end
153
+
154
+ def interpreter?
155
+ true
156
+ end
157
+
158
+ attr_accessor :multiplex
159
+
160
+ def subscription_update?
161
+ @subscription_topic && subscription?
162
+ end
163
+
164
+ # A lookahead for the root selections of this query
165
+ # @return [GraphQL::Execution::Lookahead]
166
+ def lookahead
167
+ @lookahead ||= begin
168
+ ast_node = selected_operation
169
+ root_type = warden.root_type_for_operation(ast_node.operation_type || "query")
170
+ GraphQL::Execution::Lookahead.new(query: self, root_type: root_type, ast_nodes: [ast_node])
171
+ end
172
+ end
173
+
174
+ # @api private
175
+ def result_values=(result_hash)
176
+ if @executed
177
+ raise "Invariant: Can't reassign result"
178
+ else
179
+ @executed = true
180
+ @result_values = result_hash
181
+ end
182
+ end
183
+
184
+ # @api private
185
+ attr_reader :result_values
186
+
187
+ def fragments
188
+ with_prepared_ast { @fragments }
189
+ end
190
+
191
+ def operations
192
+ with_prepared_ast { @operations }
55
193
  end
56
194
 
57
195
  # Get the result for this query, executing it once
196
+ # @return [Hash] A GraphQL response, with `"data"` and/or `"errors"` keys
58
197
  def result
59
- @result ||= begin
60
- if @validate && (validation_errors.any? || analysis_errors.any?)
61
- { "errors" => validation_errors + analysis_errors}
62
- else
63
- Executor.new(self).result
64
- end
198
+ if !@executed
199
+ Execution::Interpreter.run_all(@schema, [self], context: @context)
65
200
  end
201
+ @result ||= Query::Result.new(query: self, values: @result_values)
202
+ end
66
203
 
204
+ def executed?
205
+ @executed
67
206
  end
68
207
 
208
+ def static_errors
209
+ validation_errors + analysis_errors + context.errors
210
+ end
69
211
 
70
212
  # This is the operation to run for this query.
71
213
  # If more than one operation is present, it must be named at runtime.
72
214
  # @return [GraphQL::Language::Nodes::OperationDefinition, nil]
73
215
  def selected_operation
74
- @selected_operation ||= find_operation(@operations, @operation_name)
216
+ with_prepared_ast { @selected_operation }
75
217
  end
76
218
 
77
219
  # Determine the values for variables of this query, using default values
78
220
  # if a value isn't provided at runtime.
79
221
  #
80
- # Raises if a non-null variable isn't provided at runtime.
222
+ # If some variable is invalid, errors are added to {#validation_errors}.
223
+ #
81
224
  # @return [GraphQL::Query::Variables] Variables to apply to this query
82
225
  def variables
83
- @variables ||= GraphQL::Query::Variables.new(
84
- schema,
85
- selected_operation.variables,
86
- @provided_variables
87
- )
226
+ @variables ||= begin
227
+ with_prepared_ast {
228
+ GraphQL::Query::Variables.new(
229
+ @context,
230
+ @ast_variables,
231
+ @provided_variables,
232
+ )
233
+ }
234
+ end
88
235
  end
89
236
 
90
- def internal_representation
91
- @internal_representation ||= begin
92
- perform_validation
93
- @internal_representation
94
- end
237
+ # Node-level cache for calculating arguments. Used during execution and query analysis.
238
+ # @param ast_node [GraphQL::Language::Nodes::AbstractNode]
239
+ # @param definition [GraphQL::Schema::Field]
240
+ # @param parent_object [GraphQL::Schema::Object]
241
+ # @return Hash{Symbol => Object}
242
+ def arguments_for(ast_node, definition, parent_object: nil)
243
+ arguments_cache.fetch(ast_node, definition, parent_object)
95
244
  end
96
245
 
97
- def validation_errors
98
- @validation_errors ||= begin
99
- perform_validation
100
- @validation_errors
101
- end
246
+ def arguments_cache
247
+ @arguments_cache ||= Execution::Interpreter::ArgumentsCache.new(self)
102
248
  end
103
249
 
104
- # Node-level cache for calculating arguments. Used during execution and query analysis.
105
- # @return [GraphQL::Query::Arguments] Arguments for this node, merging default values, literal values and query variables
106
- def arguments_for(irep_node)
107
- @arguments_cache[irep_node] ||= begin
108
- GraphQL::Query::LiteralInput.from_arguments(
109
- irep_node.ast_node.arguments,
110
- irep_node.definition.arguments,
111
- self.variables
112
- )
250
+ # A version of the given query string, with:
251
+ # - Variables inlined to the query
252
+ # - Strings replaced with `<REDACTED>`
253
+ # @return [String, nil] Returns nil if the query is invalid.
254
+ def sanitized_query_string(inline_variables: true)
255
+ with_prepared_ast {
256
+ schema.sanitized_printer.new(self, inline_variables: inline_variables).sanitized_query_string
257
+ }
258
+ end
259
+
260
+ # This contains a few components:
261
+ #
262
+ # - The selected operation name (or `anonymous`)
263
+ # - The fingerprint of the query string
264
+ # - The number of given variables (for readability)
265
+ # - The fingerprint of the given variables
266
+ #
267
+ # This fingerprint can be used to track runs of the same operation-variables combination over time.
268
+ #
269
+ # @see operation_fingerprint
270
+ # @see variables_fingerprint
271
+ # @return [String] An opaque hash identifying this operation-variables combination
272
+ def fingerprint
273
+ @fingerprint ||= "#{operation_fingerprint}/#{variables_fingerprint}"
274
+ end
275
+
276
+ # @return [String] An opaque hash for identifying this query's given query string and selected operation
277
+ def operation_fingerprint
278
+ @operation_fingerprint ||= "#{selected_operation_name || "anonymous"}/#{Fingerprint.generate(query_string)}"
279
+ end
280
+
281
+ # @return [String] An opaque hash for identifying this query's given a variable values (not including defaults)
282
+ def variables_fingerprint
283
+ @variables_fingerprint ||= "#{provided_variables.size}/#{Fingerprint.generate(provided_variables.to_json)}"
284
+ end
285
+
286
+ def validation_pipeline
287
+ with_prepared_ast { @validation_pipeline }
288
+ end
289
+
290
+ def_delegators :validation_pipeline, :validation_errors,
291
+ :analyzers, :ast_analyzers, :max_depth, :max_complexity
292
+
293
+ attr_accessor :analysis_errors
294
+ def valid?
295
+ validation_pipeline.valid? && analysis_errors.empty?
296
+ end
297
+
298
+ def warden
299
+ with_prepared_ast { @warden }
300
+ end
301
+
302
+ def_delegators :warden, :get_type, :get_field, :possible_types, :root_type_for_operation
303
+
304
+ # @param abstract_type [GraphQL::UnionType, GraphQL::InterfaceType]
305
+ # @param value [Object] Any runtime value
306
+ # @return [GraphQL::ObjectType, nil] The runtime type of `value` from {Schema#resolve_type}
307
+ # @see {#possible_types} to apply filtering from `only` / `except`
308
+ def resolve_type(abstract_type, value = :__undefined__)
309
+ if value.is_a?(Symbol) && value == :__undefined__
310
+ # Old method signature
311
+ value = abstract_type
312
+ abstract_type = nil
113
313
  end
314
+ if value.is_a?(GraphQL::Schema::Object)
315
+ value = value.object
316
+ end
317
+ @resolved_types_cache[abstract_type][value]
114
318
  end
115
319
 
116
- private
320
+ def mutation?
321
+ with_prepared_ast { @mutation }
322
+ end
323
+
324
+ def query?
325
+ with_prepared_ast { @query }
326
+ end
117
327
 
118
- def perform_validation
119
- validation_result = schema.static_validator.validate(self)
120
- @validation_errors = validation_result[:errors]
121
- @internal_representation = validation_result[:irep]
328
+ # @return [void]
329
+ def merge_filters(only: nil, except: nil)
330
+ if @prepared_ast
331
+ raise "Can't add filters after preparing the query"
332
+ else
333
+ @filter = @filter.merge(only: only, except: except)
334
+ end
122
335
  nil
123
336
  end
124
337
 
338
+ def subscription?
339
+ with_prepared_ast { @subscription }
340
+ end
341
+
342
+ # @api private
343
+ def handle_or_reraise(err)
344
+ schema.handle_or_reraise(context, err)
345
+ end
346
+
347
+ private
125
348
 
126
349
  def find_operation(operations, operation_name)
127
- if operations.length == 1
350
+ if operation_name.nil? && operations.length == 1
128
351
  operations.values.first
129
- elsif operations.length == 0
130
- nil
131
352
  elsif !operations.key?(operation_name)
132
- raise OperationNameMissingError, operations.keys
353
+ nil
133
354
  else
134
- operations[operation_name]
355
+ operations.fetch(operation_name)
135
356
  end
136
357
  end
137
358
 
138
- def analysis_errors
139
- @analysis_errors ||= begin
140
- if validation_errors.any?
141
- # Can't reduce an invalid query
142
- []
143
- elsif @query_analyzers.any?
144
- reduce_results = GraphQL::Analysis.analyze_query(self, @query_analyzers)
145
- reduce_results.select { |r| r.is_a?(GraphQL::AnalysisError) }.map(&:to_h)
359
+ def prepare_ast
360
+ @prepared_ast = true
361
+ @warden ||= GraphQL::Schema::Warden.new(@filter, schema: @schema, context: @context)
362
+ parse_error = nil
363
+ @document ||= begin
364
+ if query_string
365
+ GraphQL.parse(query_string, tracer: self)
366
+ end
367
+ rescue GraphQL::ParseError => err
368
+ parse_error = err
369
+ @schema.parse_error(err, @context)
370
+ nil
371
+ end
372
+
373
+ @fragments = {}
374
+ @operations = {}
375
+ if @document
376
+ @document.definitions.each do |part|
377
+ case part
378
+ when GraphQL::Language::Nodes::FragmentDefinition
379
+ @fragments[part.name] = part
380
+ when GraphQL::Language::Nodes::OperationDefinition
381
+ @operations[part.name] = part
382
+ end
383
+ end
384
+ elsif parse_error
385
+ # This will be handled later
386
+ else
387
+ parse_error = GraphQL::ExecutionError.new("No query string was present")
388
+ @context.add_error(parse_error)
389
+ end
390
+
391
+ # Trying to execute a document
392
+ # with no operations returns an empty hash
393
+ @ast_variables = []
394
+ @mutation = false
395
+ @subscription = false
396
+ operation_name_error = nil
397
+ if @operations.any?
398
+ @selected_operation = find_operation(@operations, @operation_name)
399
+ if @selected_operation.nil?
400
+ operation_name_error = GraphQL::Query::OperationNameMissingError.new(@operation_name)
146
401
  else
147
- []
402
+ if @operation_name.nil?
403
+ @operation_name = @selected_operation.name
404
+ end
405
+ @ast_variables = @selected_operation.variables
406
+ @mutation = @selected_operation.operation_type == "mutation"
407
+ @query = @selected_operation.operation_type == "query"
408
+ @subscription = @selected_operation.operation_type == "subscription"
148
409
  end
149
410
  end
411
+
412
+ @validation_pipeline = GraphQL::Query::ValidationPipeline.new(
413
+ query: self,
414
+ parse_error: parse_error,
415
+ operation_name_error: operation_name_error,
416
+ max_depth: @max_depth,
417
+ max_complexity: @max_complexity
418
+ )
419
+ end
420
+
421
+ # Since the query string is processed at the last possible moment,
422
+ # any internal values which depend on it should be accessed within this wrapper.
423
+ def with_prepared_ast
424
+ if !@prepared_ast
425
+ prepare_ast
426
+ end
427
+ yield
150
428
  end
151
429
  end
152
430
  end
153
-
154
- require "graphql/query/arguments"
155
- require "graphql/query/context"
156
- require "graphql/query/directive_resolution"
157
- require "graphql/query/executor"
158
- require "graphql/query/literal_input"
159
- require "graphql/query/serial_execution"
160
- require "graphql/query/type_resolver"
161
- require "graphql/query/variables"
162
- require "graphql/query/input_validation_result"
163
- require "graphql/query/variable_validation_error"
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Railtie < Rails::Railtie
4
+ config.before_configuration do
5
+ # Bootsnap compile cache has similar expiration properties,
6
+ # so we assume that if the user has bootsnap setup it's ok
7
+ # to piggy back on it.
8
+ if ::Object.const_defined?("Bootsnap::CompileCache::ISeq") && Bootsnap::CompileCache::ISeq.cache_dir
9
+ Language::Parser.cache ||= Language::Cache.new(Pathname.new(Bootsnap::CompileCache::ISeq.cache_dir).join('graphql'))
10
+ end
11
+ end
12
+ end
13
+ end