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
@@ -0,0 +1,311 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Execution
4
+ # Lookahead creates a uniform interface to inspect the forthcoming selections.
5
+ #
6
+ # It assumes that the AST it's working with is valid. (So, it's safe to use
7
+ # during execution, but if you're using it directly, be sure to validate first.)
8
+ #
9
+ # A field may get access to its lookahead by adding `extras: [:lookahead]`
10
+ # to its configuration.
11
+ #
12
+ # @example looking ahead in a field
13
+ # field :articles, [Types::Article], null: false,
14
+ # extras: [:lookahead]
15
+ #
16
+ # # For example, imagine a faster database call
17
+ # # may be issued when only some fields are requested.
18
+ # #
19
+ # # Imagine that _full_ fetch must be made to satisfy `fullContent`,
20
+ # # we can look ahead to see if we need that field. If we do,
21
+ # # we make the expensive database call instead of the cheap one.
22
+ # def articles(lookahead:)
23
+ # if lookahead.selects?(:full_content)
24
+ # fetch_full_articles(object)
25
+ # else
26
+ # fetch_preview_articles(object)
27
+ # end
28
+ # end
29
+ class Lookahead
30
+ # @param query [GraphQL::Query]
31
+ # @param ast_nodes [Array<GraphQL::Language::Nodes::Field>, Array<GraphQL::Language::Nodes::OperationDefinition>]
32
+ # @param field [GraphQL::Schema::Field] if `ast_nodes` are fields, this is the field definition matching those nodes
33
+ # @param root_type [Class] if `ast_nodes` are operation definition, this is the root type for that operation
34
+ def initialize(query:, ast_nodes:, field: nil, root_type: nil, owner_type: nil)
35
+ @ast_nodes = ast_nodes.freeze
36
+ @field = field
37
+ @root_type = root_type
38
+ @query = query
39
+ @selected_type = @field ? @field.type.unwrap : root_type
40
+ @owner_type = owner_type
41
+ end
42
+
43
+ # @return [Array<GraphQL::Language::Nodes::Field>]
44
+ attr_reader :ast_nodes
45
+
46
+ # @return [GraphQL::Schema::Field]
47
+ attr_reader :field
48
+
49
+ # @return [GraphQL::Schema::Object, GraphQL::Schema::Union, GraphQL::Schema::Interface]
50
+ attr_reader :owner_type
51
+
52
+ # @return [Hash<Symbol, Object>]
53
+ def arguments
54
+ if defined?(@arguments)
55
+ @arguments
56
+ else
57
+ @arguments = if @field
58
+ @query.schema.after_lazy(@query.arguments_for(@ast_nodes.first, @field)) do |args|
59
+ args.is_a?(Execution::Interpreter::Arguments) ? args.keyword_arguments : args
60
+ end
61
+ else
62
+ nil
63
+ end
64
+ end
65
+ end
66
+
67
+ # True if this node has a selection on `field_name`.
68
+ # If `field_name` is a String, it is treated as a GraphQL-style (camelized)
69
+ # field name and used verbatim. If `field_name` is a Symbol, it is
70
+ # treated as a Ruby-style (underscored) name and camelized before comparing.
71
+ #
72
+ # If `arguments:` is provided, each provided key/value will be matched
73
+ # against the arguments in the next selection. This method will return false
74
+ # if any of the given `arguments:` are not present and matching in the next selection.
75
+ # (But, the next selection may contain _more_ than the given arguments.)
76
+ # @param field_name [String, Symbol]
77
+ # @param arguments [Hash] Arguments which must match in the selection
78
+ # @return [Boolean]
79
+ def selects?(field_name, selected_type: @selected_type, arguments: nil)
80
+ selection(field_name, selected_type: selected_type, arguments: arguments).selected?
81
+ end
82
+
83
+ # @return [Boolean] True if this lookahead represents a field that was requested
84
+ def selected?
85
+ true
86
+ end
87
+
88
+ # Like {#selects?}, but can be used for chaining.
89
+ # It returns a null object (check with {#selected?})
90
+ # @param field_name [String, Symbol]
91
+ # @return [GraphQL::Execution::Lookahead]
92
+ def selection(field_name, selected_type: @selected_type, arguments: nil)
93
+ next_field_defn = case field_name
94
+ when String
95
+ @query.get_field(selected_type, field_name)
96
+ when Symbol
97
+ # Try to avoid the `.to_s` below, if possible
98
+ all_fields = if selected_type.kind.fields?
99
+ @query.warden.fields(selected_type)
100
+ else
101
+ # Handle unions by checking possible
102
+ @query.warden
103
+ .possible_types(selected_type)
104
+ .map { |t| @query.warden.fields(t) }
105
+ .flatten
106
+ end
107
+
108
+ if (match_by_orig_name = all_fields.find { |f| f.original_name == field_name })
109
+ match_by_orig_name
110
+ else
111
+ # Symbol#name is only present on 3.0+
112
+ sym_s = field_name.respond_to?(:name) ? field_name.name : field_name.to_s
113
+ guessed_name = Schema::Member::BuildType.camelize(sym_s)
114
+ @query.get_field(selected_type, guessed_name)
115
+ end
116
+ end
117
+
118
+ if next_field_defn
119
+ next_nodes = []
120
+ @ast_nodes.each do |ast_node|
121
+ ast_node.selections.each do |selection|
122
+ find_selected_nodes(selection, next_field_defn, arguments: arguments, matches: next_nodes)
123
+ end
124
+ end
125
+
126
+ if next_nodes.any?
127
+ Lookahead.new(query: @query, ast_nodes: next_nodes, field: next_field_defn, owner_type: selected_type)
128
+ else
129
+ NULL_LOOKAHEAD
130
+ end
131
+ else
132
+ NULL_LOOKAHEAD
133
+ end
134
+ end
135
+
136
+ # Like {#selection}, but for all nodes.
137
+ # It returns a list of Lookaheads for all Selections
138
+ #
139
+ # If `arguments:` is provided, each provided key/value will be matched
140
+ # against the arguments in each selection. This method will filter the selections
141
+ # if any of the given `arguments:` do not match the given selection.
142
+ #
143
+ # @example getting the name of a selection
144
+ # def articles(lookahead:)
145
+ # next_lookaheads = lookahead.selections # => [#<GraphQL::Execution::Lookahead ...>, ...]
146
+ # next_lookaheads.map(&:name) #=> [:full_content, :title]
147
+ # end
148
+ #
149
+ # @param arguments [Hash] Arguments which must match in the selection
150
+ # @return [Array<GraphQL::Execution::Lookahead>]
151
+ def selections(arguments: nil)
152
+ subselections_by_type = {}
153
+ subselections_on_type = subselections_by_type[@selected_type] = {}
154
+
155
+ @ast_nodes.each do |node|
156
+ find_selections(subselections_by_type, subselections_on_type, @selected_type, node.selections, arguments)
157
+ end
158
+
159
+ subselections = []
160
+
161
+ subselections_by_type.each do |type, ast_nodes_by_response_key|
162
+ ast_nodes_by_response_key.each do |response_key, ast_nodes|
163
+ field_defn = @query.get_field(type, ast_nodes.first.name)
164
+ lookahead = Lookahead.new(query: @query, ast_nodes: ast_nodes, field: field_defn, owner_type: type)
165
+ subselections.push(lookahead)
166
+ end
167
+ end
168
+
169
+ subselections
170
+ end
171
+
172
+ # The method name of the field.
173
+ # It returns the method_sym of the Lookahead's field.
174
+ #
175
+ # @example getting the name of a selection
176
+ # def articles(lookahead:)
177
+ # article.selection(:full_content).name # => :full_content
178
+ # # ...
179
+ # end
180
+ #
181
+ # @return [Symbol]
182
+ def name
183
+ @field && @field.original_name
184
+ end
185
+
186
+ def inspect
187
+ "#<GraphQL::Execution::Lookahead #{@field ? "@field=#{@field.path.inspect}": "@root_type=#{@root_type}"} @ast_nodes.size=#{@ast_nodes.size}>"
188
+ end
189
+
190
+ # This is returned for {Lookahead#selection} when a non-existent field is passed
191
+ class NullLookahead < Lookahead
192
+ # No inputs required here.
193
+ def initialize
194
+ end
195
+
196
+ def selected?
197
+ false
198
+ end
199
+
200
+ def selects?(*)
201
+ false
202
+ end
203
+
204
+ def selection(*)
205
+ NULL_LOOKAHEAD
206
+ end
207
+
208
+ def selections(*)
209
+ []
210
+ end
211
+
212
+ def inspect
213
+ "#<GraphQL::Execution::Lookahead::NullLookahead>"
214
+ end
215
+ end
216
+
217
+ # A singleton, so that misses don't come with overhead.
218
+ NULL_LOOKAHEAD = NullLookahead.new
219
+
220
+ private
221
+
222
+ def skipped_by_directive?(ast_selection)
223
+ ast_selection.directives.each do |directive|
224
+ dir_defn = @query.schema.directives.fetch(directive.name)
225
+ directive_class = dir_defn
226
+ if directive_class
227
+ dir_args = @query.arguments_for(directive, dir_defn)
228
+ return true unless directive_class.static_include?(dir_args, @query.context)
229
+ end
230
+ end
231
+ false
232
+ end
233
+
234
+ def find_selections(subselections_by_type, selections_on_type, selected_type, ast_selections, arguments)
235
+ ast_selections.each do |ast_selection|
236
+ next if skipped_by_directive?(ast_selection)
237
+
238
+ case ast_selection
239
+ when GraphQL::Language::Nodes::Field
240
+ response_key = ast_selection.alias || ast_selection.name
241
+ if selections_on_type.key?(response_key)
242
+ selections_on_type[response_key] << ast_selection
243
+ elsif arguments.nil? || arguments.empty?
244
+ selections_on_type[response_key] = [ast_selection]
245
+ else
246
+ field_defn = @query.get_field(selected_type, ast_selection.name)
247
+ if arguments_match?(arguments, field_defn, ast_selection)
248
+ selections_on_type[response_key] = [ast_selection]
249
+ end
250
+ end
251
+ when GraphQL::Language::Nodes::InlineFragment
252
+ on_type = selected_type
253
+ subselections_on_type = selections_on_type
254
+ if (t = ast_selection.type)
255
+ # Assuming this is valid, that `t` will be found.
256
+ on_type = @query.get_type(t.name)
257
+ subselections_on_type = subselections_by_type[on_type] ||= {}
258
+ end
259
+ find_selections(subselections_by_type, subselections_on_type, on_type, ast_selection.selections, arguments)
260
+ when GraphQL::Language::Nodes::FragmentSpread
261
+ frag_defn = @query.fragments[ast_selection.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{ast_selection.name} (found: #{@query.fragments.keys})")
262
+ # Again, assuming a valid AST
263
+ on_type = @query.get_type(frag_defn.type.name)
264
+ subselections_on_type = subselections_by_type[on_type] ||= {}
265
+ find_selections(subselections_by_type, subselections_on_type, on_type, frag_defn.selections, arguments)
266
+ else
267
+ raise "Invariant: Unexpected selection type: #{ast_selection.class}"
268
+ end
269
+ end
270
+ end
271
+
272
+ # If a selection on `node` matches `field_name` (which is backed by `field_defn`)
273
+ # and matches the `arguments:` constraints, then add that node to `matches`
274
+ def find_selected_nodes(node, field_defn, arguments:, matches:)
275
+ return if skipped_by_directive?(node)
276
+ case node
277
+ when GraphQL::Language::Nodes::Field
278
+ if node.name == field_defn.graphql_name
279
+ if arguments.nil? || arguments.empty?
280
+ # No constraint applied
281
+ matches << node
282
+ elsif arguments_match?(arguments, field_defn, node)
283
+ matches << node
284
+ end
285
+ end
286
+ when GraphQL::Language::Nodes::InlineFragment
287
+ node.selections.each { |s| find_selected_nodes(s, field_defn, arguments: arguments, matches: matches) }
288
+ when GraphQL::Language::Nodes::FragmentSpread
289
+ frag_defn = @query.fragments[node.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{node.name} (found: #{@query.fragments.keys})")
290
+ frag_defn.selections.each { |s| find_selected_nodes(s, field_defn, arguments: arguments, matches: matches) }
291
+ else
292
+ raise "Unexpected selection comparison on #{node.class.name} (#{node})"
293
+ end
294
+ end
295
+
296
+ def arguments_match?(arguments, field_defn, field_node)
297
+ query_kwargs = @query.arguments_for(field_node, field_defn)
298
+ arguments.all? do |arg_name, arg_value|
299
+ arg_name_sym = if arg_name.is_a?(String)
300
+ Schema::Member::BuildType.underscore(arg_name).to_sym
301
+ else
302
+ arg_name
303
+ end
304
+
305
+ # Make sure the constraint is present with a matching value
306
+ query_kwargs.key?(arg_name_sym) && query_kwargs[arg_name_sym] == arg_value
307
+ end
308
+ end
309
+ end
310
+ end
311
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Execution
4
+ # Execute multiple queries under the same multiplex "umbrella".
5
+ # They can share a batching context and reduce redundant database hits.
6
+ #
7
+ # The flow is:
8
+ #
9
+ # - Multiplex instrumentation setup
10
+ # - Query instrumentation setup
11
+ # - Analyze the multiplex + each query
12
+ # - Begin each query
13
+ # - Resolve lazy values, breadth-first across all queries
14
+ # - Finish each query (eg, get errors)
15
+ # - Query instrumentation teardown
16
+ # - Multiplex instrumentation teardown
17
+ #
18
+ # If one query raises an application error, all queries will be in undefined states.
19
+ #
20
+ # Validation errors and {GraphQL::ExecutionError}s are handled in isolation:
21
+ # one of these errors in one query will not affect the other queries.
22
+ #
23
+ # @see {Schema#multiplex} for public API
24
+ # @api private
25
+ class Multiplex
26
+ include Tracing::Traceable
27
+
28
+ attr_reader :context, :queries, :schema, :max_complexity, :dataloader
29
+
30
+ def initialize(schema:, queries:, context:, max_complexity:)
31
+ @schema = schema
32
+ @queries = queries
33
+ @queries.each { |q| q.multiplex = self }
34
+ @context = context
35
+ @dataloader = @context[:dataloader] ||= @schema.dataloader_class.new
36
+ @tracers = schema.tracers + (context[:tracers] || [])
37
+ # Support `context: {backtrace: true}`
38
+ if context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
39
+ @tracers << GraphQL::Backtrace::Tracer
40
+ end
41
+ @max_complexity = max_complexity
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/execution/directive_checks"
3
+ require "graphql/execution/interpreter"
4
+ require "graphql/execution/lazy"
5
+ require "graphql/execution/lookahead"
6
+ require "graphql/execution/multiplex"
7
+ require "graphql/execution/errors"
8
+
9
+ module GraphQL
10
+ module Execution
11
+ # @api private
12
+ class Skip < GraphQL::Error; end
13
+
14
+ # Just a singleton for implementing {Query::Context#skip}
15
+ # @api private
16
+ SKIP = Skip.new
17
+ end
18
+ end
@@ -1,11 +1,33 @@
1
+ # frozen_string_literal: true
1
2
  module GraphQL
2
3
  # If a field's resolve function returns a {ExecutionError},
3
4
  # the error will be inserted into the response's `"errors"` key
4
5
  # and the field will resolve to `nil`.
5
6
  class ExecutionError < GraphQL::Error
6
- # @return [GraphQL::Language::Nodes::Field] the field where the error occured
7
+ # @return [GraphQL::Language::Nodes::Field] the field where the error occurred
7
8
  attr_accessor :ast_node
8
9
 
10
+ # @return [String] an array describing the JSON-path into the execution
11
+ # response which corresponds to this error.
12
+ attr_accessor :path
13
+
14
+ # @return [Hash] Optional data for error objects
15
+ # @deprecated Use `extensions` instead of `options`. The GraphQL spec
16
+ # recommends that any custom entries in an error be under the
17
+ # `extensions` key.
18
+ attr_accessor :options
19
+
20
+ # @return [Hash] Optional custom data for error objects which will be added
21
+ # under the `extensions` key.
22
+ attr_accessor :extensions
23
+
24
+ def initialize(message, ast_node: nil, options: nil, extensions: nil)
25
+ @ast_node = ast_node
26
+ @options = options
27
+ @extensions = extensions
28
+ super(message)
29
+ end
30
+
9
31
  # @return [Hash] An entry for the response's "errors" key
10
32
  def to_h
11
33
  hash = {
@@ -19,6 +41,17 @@ module GraphQL
19
41
  }
20
42
  ]
21
43
  end
44
+ if path
45
+ hash["path"] = path
46
+ end
47
+ if options
48
+ hash.merge!(options)
49
+ end
50
+ if extensions
51
+ hash["extensions"] = extensions.each_with_object({}) { |(key, value), ext|
52
+ ext[key.to_s] = value
53
+ }
54
+ end
22
55
  hash
23
56
  end
24
57
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ # @api private
4
+ class Filter
5
+ def initialize(only: nil, except: nil)
6
+ @only = only
7
+ @except = except
8
+ end
9
+
10
+ # Returns true if `member, ctx` passes this filter
11
+ def call(member, ctx)
12
+ (@only ? @only.call(member, ctx) : true) &&
13
+ (@except ? !@except.call(member, ctx) : true)
14
+ end
15
+
16
+ def merge(only: nil, except: nil)
17
+ onlies = [self].concat(Array(only))
18
+ merged_only = MergedOnly.build(onlies)
19
+ merged_except = MergedExcept.build(Array(except))
20
+ self.class.new(only: merged_only, except: merged_except)
21
+ end
22
+
23
+ private
24
+
25
+ class MergedOnly
26
+ def initialize(first, second)
27
+ @first = first
28
+ @second = second
29
+ end
30
+
31
+ def call(member, ctx)
32
+ @first.call(member, ctx) && @second.call(member, ctx)
33
+ end
34
+
35
+ def self.build(onlies)
36
+ case onlies.size
37
+ when 0
38
+ nil
39
+ when 1
40
+ onlies[0]
41
+ else
42
+ onlies.reduce { |memo, only| self.new(memo, only) }
43
+ end
44
+ end
45
+ end
46
+
47
+ class MergedExcept < MergedOnly
48
+ def call(member, ctx)
49
+ @first.call(member, ctx) || @second.call(member, ctx)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ # This error is raised when `Types::Int` is given an input value outside of 32-bit integer range.
4
+ #
5
+ # For really big integer values, consider `GraphQL::Types::BigInt`
6
+ #
7
+ # @see GraphQL::Types::Int which raises this error
8
+ class IntegerDecodingError < GraphQL::RuntimeTypeError
9
+ # The value which couldn't be decoded
10
+ attr_reader :integer_value
11
+
12
+ def initialize(value)
13
+ @integer_value = value
14
+ super("Integer out of bounds: #{value}. \nConsider using GraphQL::Types::BigInt instead.")
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ # This error is raised when `Types::Int` is asked to return a value outside of 32-bit integer range.
4
+ #
5
+ # For values outside that range, consider:
6
+ #
7
+ # - `ID` for database primary keys or other identifiers
8
+ # - `GraphQL::Types::BigInt` for really big integer values
9
+ #
10
+ # @see GraphQL::Types::Int which raises this error
11
+ class IntegerEncodingError < GraphQL::RuntimeTypeError
12
+ # The value which couldn't be encoded
13
+ attr_reader :integer_value
14
+
15
+ # @return [GraphQL::Schema::Field] The field that returned a too-big integer
16
+ attr_reader :field
17
+
18
+ # @return [Array<String, Integer>] Where the field appeared in the GraphQL response
19
+ attr_reader :path
20
+
21
+ def initialize(value, context:)
22
+ @integer_value = value
23
+ @field = context[:current_field]
24
+ @path = context[:current_path]
25
+ message = "Integer out of bounds: #{value}".dup
26
+ if @path
27
+ message << " @ #{@path.join(".")}"
28
+ end
29
+ if @field
30
+ message << " (#{@field.path})"
31
+ end
32
+ message << ". Consider using ID or GraphQL::Types::BigInt instead."
33
+ super(message)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Introspection
4
+ class BaseObject < GraphQL::Schema::Object
5
+ introspection(true)
6
+
7
+ def self.field(*args, **kwargs, &block)
8
+ kwargs[:introspection] = true
9
+ super(*args, **kwargs, &block)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,8 +1,15 @@
1
- GraphQL::Introspection::DirectiveLocationEnum = GraphQL::EnumType.define do
2
- name "__DirectiveLocation"
3
- description "Parts of the query where a directive may be located"
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Introspection
4
+ class DirectiveLocationEnum < GraphQL::Schema::Enum
5
+ graphql_name "__DirectiveLocation"
6
+ description "A Directive can be adjacent to many parts of the GraphQL language, "\
7
+ "a __DirectiveLocation describes one such possible adjacencies."
4
8
 
5
- GraphQL::Directive::LOCATIONS.each do |location|
6
- value(location.to_s, value: location)
9
+ GraphQL::Schema::Directive::LOCATIONS.each do |location|
10
+ value(location.to_s, GraphQL::Schema::Directive::LOCATION_DESCRIPTIONS[location], value: location)
11
+ end
12
+ introspection true
13
+ end
7
14
  end
8
15
  end
@@ -1,11 +1,31 @@
1
- GraphQL::Introspection::DirectiveType = GraphQL::ObjectType.define do
2
- name "__Directive"
3
- description "A query directive in this schema"
4
- field :name, !types.String, "The name of this directive"
5
- field :description, types.String, "The description for this type"
6
- field :args, field: GraphQL::Introspection::ArgumentsField
7
- field :locations, !types[!GraphQL::Introspection::DirectiveLocationEnum]
8
- field :onOperation, !types.Boolean, "Does this directive apply to operations?", deprecation_reason: "Moved to 'locations' field", property: :on_operation?
9
- field :onFragment, !types.Boolean, "Does this directive apply to fragments?", deprecation_reason: "Moved to 'locations' field", property: :on_fragment?
10
- field :onField, !types.Boolean, "Does this directive apply to fields?", deprecation_reason: "Moved to 'locations' field", property: :on_field?
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Introspection
4
+ class DirectiveType < Introspection::BaseObject
5
+ graphql_name "__Directive"
6
+ description "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document."\
7
+ "\n\n"\
8
+ "In some cases, you need to provide options to alter GraphQL's execution behavior "\
9
+ "in ways field arguments will not suffice, such as conditionally including or "\
10
+ "skipping a field. Directives provide this by describing additional information "\
11
+ "to the executor."
12
+ field :name, String, null: false, method: :graphql_name
13
+ field :description, String
14
+ field :locations, [GraphQL::Schema::LateBoundType.new("__DirectiveLocation")], null: false
15
+ field :args, [GraphQL::Schema::LateBoundType.new("__InputValue")], null: false do
16
+ argument :include_deprecated, Boolean, required: false, default_value: false
17
+ end
18
+ field :on_operation, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_operation?
19
+ field :on_fragment, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_fragment?
20
+ field :on_field, Boolean, null: false, deprecation_reason: "Use `locations`.", method: :on_field?
21
+
22
+ field :is_repeatable, Boolean, method: :repeatable?
23
+
24
+ def args(include_deprecated:)
25
+ args = @context.warden.arguments(@object)
26
+ args = args.reject(&:deprecation_reason) unless include_deprecated
27
+ args
28
+ end
29
+ end
30
+ end
11
31
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Introspection
4
+ class DynamicFields < Introspection::BaseObject
5
+ field :__typename, String, "The name of this type", null: false
6
+
7
+ def __typename
8
+ object.class.graphql_name
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Introspection
4
+ class EntryPoints < Introspection::BaseObject
5
+ field :__schema, GraphQL::Schema::LateBoundType.new("__Schema"), "This GraphQL schema", null: false
6
+ field :__type, GraphQL::Schema::LateBoundType.new("__Type"), "A type in the GraphQL system" do
7
+ argument :name, String
8
+ end
9
+
10
+ def __schema
11
+ # Apply wrapping manually since this field isn't wrapped by instrumentation
12
+ schema = @context.query.schema
13
+ schema_type = schema.introspection_system.types["__Schema"]
14
+ schema_type.authorized_new(schema, @context)
15
+ end
16
+
17
+ def __type(name:)
18
+ context.warden.reachable_type?(name) ? context.warden.get_type(name) : nil
19
+ end
20
+ end
21
+ end
22
+ end