graphql 1.9.5 → 1.13.19

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 (659) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/graphql/core.rb +21 -9
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/install/templates/base_mutation.erb +10 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
  9. data/lib/generators/graphql/install_generator.rb +48 -8
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/loader_generator.rb +1 -0
  12. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_generator.rb +6 -30
  15. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  16. data/lib/generators/graphql/object_generator.rb +28 -12
  17. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  18. data/lib/generators/graphql/relay.rb +63 -0
  19. data/lib/generators/graphql/relay_generator.rb +21 -0
  20. data/lib/generators/graphql/scalar_generator.rb +4 -2
  21. data/lib/generators/graphql/templates/base_argument.erb +6 -0
  22. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  23. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  24. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  25. data/lib/generators/graphql/templates/base_field.erb +7 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +3 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +4 -0
  28. data/lib/generators/graphql/templates/base_object.erb +3 -0
  29. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  30. data/lib/generators/graphql/templates/base_union.erb +2 -0
  31. data/lib/generators/graphql/templates/enum.erb +7 -1
  32. data/lib/generators/graphql/templates/graphql_controller.erb +21 -12
  33. data/lib/generators/graphql/templates/input.erb +9 -0
  34. data/lib/generators/graphql/templates/interface.erb +6 -2
  35. data/lib/generators/graphql/templates/loader.erb +2 -0
  36. data/lib/generators/graphql/templates/mutation.erb +3 -1
  37. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  38. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  40. data/lib/generators/graphql/templates/node_type.erb +9 -0
  41. data/lib/generators/graphql/templates/object.erb +7 -3
  42. data/lib/generators/graphql/templates/query_type.erb +3 -3
  43. data/lib/generators/graphql/templates/scalar.erb +5 -1
  44. data/lib/generators/graphql/templates/schema.erb +23 -28
  45. data/lib/generators/graphql/templates/union.erb +6 -2
  46. data/lib/generators/graphql/type_generator.rb +47 -10
  47. data/lib/generators/graphql/union_generator.rb +5 -5
  48. data/lib/graphql/analysis/analyze_query.rb +7 -0
  49. data/lib/graphql/analysis/ast/analyzer.rb +34 -12
  50. data/lib/graphql/analysis/ast/field_usage.rb +29 -2
  51. data/lib/graphql/analysis/ast/max_query_complexity.rb +3 -3
  52. data/lib/graphql/analysis/ast/max_query_depth.rb +7 -3
  53. data/lib/graphql/analysis/ast/query_complexity.rb +179 -64
  54. data/lib/graphql/analysis/ast/query_depth.rb +16 -26
  55. data/lib/graphql/analysis/ast/visitor.rb +46 -32
  56. data/lib/graphql/analysis/ast.rb +23 -14
  57. data/lib/graphql/analysis/query_depth.rb +4 -17
  58. data/lib/graphql/argument.rb +16 -38
  59. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  60. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  61. data/lib/graphql/backtrace/table.rb +44 -5
  62. data/lib/graphql/backtrace/traced_error.rb +0 -1
  63. data/lib/graphql/backtrace/tracer.rb +40 -9
  64. data/lib/graphql/backtrace.rb +28 -19
  65. data/lib/graphql/backwards_compatibility.rb +2 -1
  66. data/lib/graphql/base_type.rb +11 -5
  67. data/lib/graphql/boolean_type.rb +1 -1
  68. data/lib/graphql/coercion_error.rb +8 -0
  69. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
  70. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  71. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +1 -1
  72. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  73. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
  74. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  75. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  76. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  77. data/lib/graphql/dataloader/request.rb +19 -0
  78. data/lib/graphql/dataloader/request_all.rb +19 -0
  79. data/lib/graphql/dataloader/source.rb +155 -0
  80. data/lib/graphql/dataloader.rb +308 -0
  81. data/lib/graphql/date_encoding_error.rb +16 -0
  82. data/lib/graphql/define/assign_enum_value.rb +1 -1
  83. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  84. data/lib/graphql/define/assign_object_field.rb +3 -3
  85. data/lib/graphql/define/defined_object_proxy.rb +3 -0
  86. data/lib/graphql/define/instance_definable.rb +65 -110
  87. data/lib/graphql/define/type_definer.rb +5 -5
  88. data/lib/graphql/deprecated_dsl.rb +18 -5
  89. data/lib/graphql/deprecation.rb +9 -0
  90. data/lib/graphql/directive/deprecated_directive.rb +1 -12
  91. data/lib/graphql/directive/include_directive.rb +1 -1
  92. data/lib/graphql/directive/skip_directive.rb +1 -1
  93. data/lib/graphql/directive.rb +9 -6
  94. data/lib/graphql/enum_type.rb +14 -74
  95. data/lib/graphql/execution/directive_checks.rb +2 -2
  96. data/lib/graphql/execution/errors.rb +163 -0
  97. data/lib/graphql/execution/execute.rb +10 -3
  98. data/lib/graphql/execution/instrumentation.rb +1 -1
  99. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  100. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  101. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  102. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  103. data/lib/graphql/execution/interpreter/resolve.rb +37 -25
  104. data/lib/graphql/execution/interpreter/runtime.rb +737 -376
  105. data/lib/graphql/execution/interpreter.rb +42 -19
  106. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  107. data/lib/graphql/execution/lazy.rb +5 -1
  108. data/lib/graphql/execution/lookahead.rb +39 -114
  109. data/lib/graphql/execution/multiplex.rb +58 -29
  110. data/lib/graphql/execution.rb +1 -0
  111. data/lib/graphql/execution_error.rb +3 -2
  112. data/lib/graphql/field.rb +15 -119
  113. data/lib/graphql/filter.rb +1 -1
  114. data/lib/graphql/float_type.rb +1 -1
  115. data/lib/graphql/function.rb +6 -31
  116. data/lib/graphql/id_type.rb +1 -1
  117. data/lib/graphql/input_object_type.rb +11 -26
  118. data/lib/graphql/int_type.rb +1 -1
  119. data/lib/graphql/integer_decoding_error.rb +17 -0
  120. data/lib/graphql/integer_encoding_error.rb +18 -2
  121. data/lib/graphql/interface_type.rb +10 -24
  122. data/lib/graphql/internal_representation/document.rb +2 -2
  123. data/lib/graphql/internal_representation/rewrite.rb +1 -1
  124. data/lib/graphql/internal_representation/scope.rb +2 -2
  125. data/lib/graphql/internal_representation/visit.rb +2 -2
  126. data/lib/graphql/introspection/base_object.rb +2 -5
  127. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  128. data/lib/graphql/introspection/directive_type.rb +12 -6
  129. data/lib/graphql/introspection/entry_points.rb +9 -8
  130. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  131. data/lib/graphql/introspection/field_type.rb +9 -5
  132. data/lib/graphql/introspection/input_value_type.rb +41 -11
  133. data/lib/graphql/introspection/introspection_query.rb +6 -92
  134. data/lib/graphql/introspection/schema_type.rb +13 -12
  135. data/lib/graphql/introspection/type_type.rb +27 -17
  136. data/lib/graphql/introspection.rb +99 -0
  137. data/lib/graphql/invalid_null_error.rb +18 -0
  138. data/lib/graphql/language/block_string.rb +22 -7
  139. data/lib/graphql/language/cache.rb +37 -0
  140. data/lib/graphql/language/definition_slice.rb +21 -10
  141. data/lib/graphql/language/document_from_schema_definition.rb +126 -67
  142. data/lib/graphql/language/lexer.rb +180 -141
  143. data/lib/graphql/language/lexer.rl +75 -51
  144. data/lib/graphql/language/nodes.rb +92 -108
  145. data/lib/graphql/language/parser.rb +933 -897
  146. data/lib/graphql/language/parser.y +129 -103
  147. data/lib/graphql/language/printer.rb +11 -2
  148. data/lib/graphql/language/sanitized_printer.rb +222 -0
  149. data/lib/graphql/language/token.rb +1 -1
  150. data/lib/graphql/language/visitor.rb +11 -8
  151. data/lib/graphql/language.rb +3 -1
  152. data/lib/graphql/name_validator.rb +2 -7
  153. data/lib/graphql/non_null_type.rb +0 -10
  154. data/lib/graphql/object_type.rb +47 -58
  155. data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
  156. data/lib/graphql/pagination/array_connection.rb +77 -0
  157. data/lib/graphql/pagination/connection.rb +226 -0
  158. data/lib/graphql/pagination/connections.rb +160 -0
  159. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  160. data/lib/graphql/pagination/relation_connection.rb +226 -0
  161. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  162. data/lib/graphql/pagination.rb +6 -0
  163. data/lib/graphql/parse_error.rb +0 -1
  164. data/lib/graphql/query/arguments.rb +29 -19
  165. data/lib/graphql/query/arguments_cache.rb +1 -2
  166. data/lib/graphql/query/context.rb +81 -14
  167. data/lib/graphql/query/executor.rb +0 -1
  168. data/lib/graphql/query/fingerprint.rb +26 -0
  169. data/lib/graphql/query/input_validation_result.rb +32 -6
  170. data/lib/graphql/query/literal_input.rb +31 -10
  171. data/lib/graphql/query/null_context.rb +28 -8
  172. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  173. data/lib/graphql/query/serial_execution.rb +1 -0
  174. data/lib/graphql/query/validation_pipeline.rb +6 -4
  175. data/lib/graphql/query/variable_validation_error.rb +3 -3
  176. data/lib/graphql/query/variables.rb +51 -9
  177. data/lib/graphql/query.rb +97 -23
  178. data/lib/graphql/railtie.rb +9 -1
  179. data/lib/graphql/rake_task/validate.rb +3 -0
  180. data/lib/graphql/rake_task.rb +12 -9
  181. data/lib/graphql/relay/array_connection.rb +11 -13
  182. data/lib/graphql/relay/base_connection.rb +33 -16
  183. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  184. data/lib/graphql/relay/connection_type.rb +18 -4
  185. data/lib/graphql/relay/edge_type.rb +1 -0
  186. data/lib/graphql/relay/edges_instrumentation.rb +1 -2
  187. data/lib/graphql/relay/global_id_resolve.rb +1 -2
  188. data/lib/graphql/relay/mutation.rb +3 -87
  189. data/lib/graphql/relay/node.rb +5 -2
  190. data/lib/graphql/relay/page_info.rb +1 -1
  191. data/lib/graphql/relay/range_add.rb +27 -9
  192. data/lib/graphql/relay/relation_connection.rb +17 -15
  193. data/lib/graphql/relay/type_extensions.rb +2 -0
  194. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  195. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  196. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  197. data/lib/graphql/rubocop.rb +4 -0
  198. data/lib/graphql/scalar_type.rb +18 -62
  199. data/lib/graphql/schema/addition.rb +247 -0
  200. data/lib/graphql/schema/argument.rb +289 -11
  201. data/lib/graphql/schema/base_64_bp.rb +3 -2
  202. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  203. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  204. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  205. data/lib/graphql/schema/build_from_definition.rb +323 -203
  206. data/lib/graphql/schema/built_in_types.rb +5 -5
  207. data/lib/graphql/schema/default_type_error.rb +2 -0
  208. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  209. data/lib/graphql/schema/directive/feature.rb +2 -2
  210. data/lib/graphql/schema/directive/flagged.rb +57 -0
  211. data/lib/graphql/schema/directive/include.rb +2 -2
  212. data/lib/graphql/schema/directive/skip.rb +2 -2
  213. data/lib/graphql/schema/directive/transform.rb +14 -2
  214. data/lib/graphql/schema/directive.rb +136 -6
  215. data/lib/graphql/schema/enum.rb +121 -12
  216. data/lib/graphql/schema/enum_value.rb +23 -6
  217. data/lib/graphql/schema/field/connection_extension.rb +46 -20
  218. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  219. data/lib/graphql/schema/field.rb +515 -191
  220. data/lib/graphql/schema/field_extension.rb +89 -2
  221. data/lib/graphql/schema/find_inherited_value.rb +36 -0
  222. data/lib/graphql/schema/finder.rb +16 -14
  223. data/lib/graphql/schema/input_object.rb +178 -34
  224. data/lib/graphql/schema/interface.rb +35 -25
  225. data/lib/graphql/schema/introspection_system.rb +111 -35
  226. data/lib/graphql/schema/late_bound_type.rb +3 -2
  227. data/lib/graphql/schema/list.rb +65 -1
  228. data/lib/graphql/schema/loader.rb +147 -97
  229. data/lib/graphql/schema/member/accepts_definition.rb +15 -3
  230. data/lib/graphql/schema/member/base_dsl_methods.rb +40 -45
  231. data/lib/graphql/schema/member/build_type.rb +19 -8
  232. data/lib/graphql/schema/member/cached_graphql_definition.rb +34 -2
  233. data/lib/graphql/schema/member/has_arguments.rb +212 -22
  234. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  235. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  236. data/lib/graphql/schema/member/has_directives.rb +98 -0
  237. data/lib/graphql/schema/member/has_fields.rb +113 -28
  238. data/lib/graphql/schema/member/has_interfaces.rb +100 -0
  239. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  240. data/lib/graphql/schema/member/has_validators.rb +31 -0
  241. data/lib/graphql/schema/member/instrumentation.rb +6 -2
  242. data/lib/graphql/schema/member/relay_shortcuts.rb +2 -2
  243. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  244. data/lib/graphql/schema/member/validates_input.rb +33 -0
  245. data/lib/graphql/schema/member.rb +11 -0
  246. data/lib/graphql/schema/middleware_chain.rb +1 -1
  247. data/lib/graphql/schema/mutation.rb +5 -1
  248. data/lib/graphql/schema/non_null.rb +37 -1
  249. data/lib/graphql/schema/object.rb +52 -37
  250. data/lib/graphql/schema/possible_types.rb +12 -7
  251. data/lib/graphql/schema/printer.rb +17 -34
  252. data/lib/graphql/schema/relay_classic_mutation.rb +51 -7
  253. data/lib/graphql/schema/resolver/has_payload_type.rb +36 -5
  254. data/lib/graphql/schema/resolver.rb +159 -59
  255. data/lib/graphql/schema/scalar.rb +43 -3
  256. data/lib/graphql/schema/subscription.rb +83 -25
  257. data/lib/graphql/schema/timeout.rb +123 -0
  258. data/lib/graphql/schema/timeout_middleware.rb +6 -3
  259. data/lib/graphql/schema/traversal.rb +2 -2
  260. data/lib/graphql/schema/type_expression.rb +21 -13
  261. data/lib/graphql/schema/type_membership.rb +48 -0
  262. data/lib/graphql/schema/union.rb +67 -6
  263. data/lib/graphql/schema/unique_within_type.rb +1 -2
  264. data/lib/graphql/schema/validation.rb +30 -8
  265. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  266. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  267. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  268. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  269. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  270. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  271. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  272. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  273. data/lib/graphql/schema/validator.rb +171 -0
  274. data/lib/graphql/schema/warden.rb +263 -30
  275. data/lib/graphql/schema/wrapper.rb +1 -1
  276. data/lib/graphql/schema.rb +1016 -256
  277. data/lib/graphql/static_validation/all_rules.rb +2 -0
  278. data/lib/graphql/static_validation/base_visitor.rb +17 -10
  279. data/lib/graphql/static_validation/definition_dependencies.rb +21 -13
  280. data/lib/graphql/static_validation/error.rb +3 -1
  281. data/lib/graphql/static_validation/literal_validator.rb +52 -27
  282. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +46 -79
  283. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +23 -6
  284. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  285. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  286. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  287. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -2
  288. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  289. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  290. data/lib/graphql/static_validation/rules/fields_will_merge.rb +105 -55
  291. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  292. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  293. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  294. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  295. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  296. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  297. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  298. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -3
  299. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
  300. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  301. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  302. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  303. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  304. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  305. data/lib/graphql/static_validation/type_stack.rb +2 -2
  306. data/lib/graphql/static_validation/validation_context.rb +13 -3
  307. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  308. data/lib/graphql/static_validation/validator.rb +43 -9
  309. data/lib/graphql/static_validation.rb +1 -0
  310. data/lib/graphql/string_encoding_error.rb +13 -3
  311. data/lib/graphql/string_type.rb +1 -1
  312. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +123 -22
  313. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  314. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
  315. data/lib/graphql/subscriptions/event.rb +94 -26
  316. data/lib/graphql/subscriptions/instrumentation.rb +10 -6
  317. data/lib/graphql/subscriptions/serialize.rb +53 -6
  318. data/lib/graphql/subscriptions/subscription_root.rb +15 -5
  319. data/lib/graphql/subscriptions.rb +122 -54
  320. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  321. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  322. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  323. data/lib/graphql/tracing/data_dog_tracing.rb +32 -2
  324. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  325. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  326. data/lib/graphql/tracing/platform_tracing.rb +66 -7
  327. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  328. data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
  329. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  330. data/lib/graphql/tracing/skylight_tracing.rb +9 -0
  331. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  332. data/lib/graphql/tracing.rb +15 -35
  333. data/lib/graphql/types/big_int.rb +5 -1
  334. data/lib/graphql/types/int.rb +10 -3
  335. data/lib/graphql/types/iso_8601_date.rb +42 -0
  336. data/lib/graphql/types/iso_8601_date_time.rb +32 -8
  337. data/lib/graphql/types/relay/base_connection.rb +6 -88
  338. data/lib/graphql/types/relay/base_edge.rb +2 -37
  339. data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
  340. data/lib/graphql/types/relay/default_relay.rb +31 -0
  341. data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
  342. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  343. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  344. data/lib/graphql/types/relay/node.rb +2 -4
  345. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  346. data/lib/graphql/types/relay/node_field.rb +4 -23
  347. data/lib/graphql/types/relay/nodes_field.rb +16 -18
  348. data/lib/graphql/types/relay/page_info.rb +2 -14
  349. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  350. data/lib/graphql/types/relay.rb +11 -3
  351. data/lib/graphql/types/string.rb +8 -2
  352. data/lib/graphql/types.rb +1 -0
  353. data/lib/graphql/unauthorized_error.rb +2 -2
  354. data/lib/graphql/union_type.rb +61 -46
  355. data/lib/graphql/unresolved_type_error.rb +2 -2
  356. data/lib/graphql/upgrader/member.rb +150 -112
  357. data/lib/graphql/upgrader/schema.rb +1 -0
  358. data/lib/graphql/version.rb +1 -1
  359. data/lib/graphql.rb +89 -18
  360. data/readme.md +4 -7
  361. metadata +115 -703
  362. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  363. data/lib/graphql/literal_validation_error.rb +0 -6
  364. data/lib/graphql/types/relay/base_field.rb +0 -22
  365. data/lib/graphql/types/relay/base_interface.rb +0 -29
  366. data/lib/graphql/types/relay/base_object.rb +0 -26
  367. data/spec/dummy/Gemfile +0 -12
  368. data/spec/dummy/Gemfile.lock +0 -157
  369. data/spec/dummy/README.md +0 -24
  370. data/spec/dummy/Rakefile +0 -7
  371. data/spec/dummy/app/assets/config/manifest.js +0 -1
  372. data/spec/dummy/app/assets/javascripts/application.js +0 -66
  373. data/spec/dummy/app/channels/application_cable/channel.rb +0 -5
  374. data/spec/dummy/app/channels/application_cable/connection.rb +0 -5
  375. data/spec/dummy/app/channels/graphql_channel.rb +0 -116
  376. data/spec/dummy/app/controllers/application_controller.rb +0 -4
  377. data/spec/dummy/app/controllers/pages_controller.rb +0 -5
  378. data/spec/dummy/app/helpers/application_helper.rb +0 -3
  379. data/spec/dummy/app/jobs/application_job.rb +0 -3
  380. data/spec/dummy/app/views/layouts/application.html.erb +0 -12
  381. data/spec/dummy/app/views/pages/show.html +0 -16
  382. data/spec/dummy/bin/bundle +0 -4
  383. data/spec/dummy/bin/rails +0 -5
  384. data/spec/dummy/bin/rake +0 -5
  385. data/spec/dummy/bin/setup +0 -31
  386. data/spec/dummy/bin/update +0 -27
  387. data/spec/dummy/bin/yarn +0 -12
  388. data/spec/dummy/config/application.rb +0 -30
  389. data/spec/dummy/config/boot.rb +0 -4
  390. data/spec/dummy/config/cable.yml +0 -10
  391. data/spec/dummy/config/environment.rb +0 -6
  392. data/spec/dummy/config/environments/development.rb +0 -40
  393. data/spec/dummy/config/environments/production.rb +0 -76
  394. data/spec/dummy/config/environments/test.rb +0 -37
  395. data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -9
  396. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
  397. data/spec/dummy/config/initializers/cookies_serializer.rb +0 -6
  398. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -5
  399. data/spec/dummy/config/initializers/inflections.rb +0 -17
  400. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  401. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -10
  402. data/spec/dummy/config/locales/en.yml +0 -33
  403. data/spec/dummy/config/puma.rb +0 -57
  404. data/spec/dummy/config/routes.rb +0 -4
  405. data/spec/dummy/config/secrets.yml +0 -32
  406. data/spec/dummy/config.ru +0 -6
  407. data/spec/dummy/log/test.log +0 -199
  408. data/spec/dummy/package.json +0 -5
  409. data/spec/dummy/public/404.html +0 -67
  410. data/spec/dummy/public/422.html +0 -67
  411. data/spec/dummy/public/500.html +0 -66
  412. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  413. data/spec/dummy/public/apple-touch-icon.png +0 -0
  414. data/spec/dummy/public/favicon.ico +0 -0
  415. data/spec/dummy/public/robots.txt +0 -1
  416. data/spec/dummy/test/application_system_test_case.rb +0 -6
  417. data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -45
  418. data/spec/dummy/test/test_helper.rb +0 -4
  419. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  420. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +0 -1
  421. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +0 -1
  422. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +0 -1
  423. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +0 -3
  424. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  425. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -2
  426. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -2
  427. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  428. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  429. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +0 -1
  430. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  431. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +0 -1
  432. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +0 -3
  433. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +0 -1
  434. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +0 -1
  435. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  436. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +0 -1
  437. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  438. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  439. data/spec/fixtures/upgrader/account.original.rb +0 -19
  440. data/spec/fixtures/upgrader/account.transformed.rb +0 -20
  441. data/spec/fixtures/upgrader/blame_range.original.rb +0 -43
  442. data/spec/fixtures/upgrader/blame_range.transformed.rb +0 -30
  443. data/spec/fixtures/upgrader/date_time.original.rb +0 -24
  444. data/spec/fixtures/upgrader/date_time.transformed.rb +0 -23
  445. data/spec/fixtures/upgrader/delete_project.original.rb +0 -28
  446. data/spec/fixtures/upgrader/delete_project.transformed.rb +0 -27
  447. data/spec/fixtures/upgrader/gist_order_field.original.rb +0 -14
  448. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +0 -13
  449. data/spec/fixtures/upgrader/increment_count.original.rb +0 -59
  450. data/spec/fixtures/upgrader/increment_count.transformed.rb +0 -50
  451. data/spec/fixtures/upgrader/photo.original.rb +0 -10
  452. data/spec/fixtures/upgrader/photo.transformed.rb +0 -12
  453. data/spec/fixtures/upgrader/release_order.original.rb +0 -15
  454. data/spec/fixtures/upgrader/release_order.transformed.rb +0 -14
  455. data/spec/fixtures/upgrader/starrable.original.rb +0 -49
  456. data/spec/fixtures/upgrader/starrable.transformed.rb +0 -46
  457. data/spec/fixtures/upgrader/subscribable.original.rb +0 -55
  458. data/spec/fixtures/upgrader/subscribable.transformed.rb +0 -51
  459. data/spec/fixtures/upgrader/type_x.original.rb +0 -65
  460. data/spec/fixtures/upgrader/type_x.transformed.rb +0 -56
  461. data/spec/graphql/analysis/analyze_query_spec.rb +0 -272
  462. data/spec/graphql/analysis/ast/field_usage_spec.rb +0 -51
  463. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +0 -120
  464. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +0 -114
  465. data/spec/graphql/analysis/ast/query_complexity_spec.rb +0 -299
  466. data/spec/graphql/analysis/ast/query_depth_spec.rb +0 -108
  467. data/spec/graphql/analysis/ast_spec.rb +0 -269
  468. data/spec/graphql/analysis/field_usage_spec.rb +0 -62
  469. data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -102
  470. data/spec/graphql/analysis/max_query_depth_spec.rb +0 -101
  471. data/spec/graphql/analysis/query_complexity_spec.rb +0 -301
  472. data/spec/graphql/analysis/query_depth_spec.rb +0 -81
  473. data/spec/graphql/argument_spec.rb +0 -159
  474. data/spec/graphql/authorization_spec.rb +0 -974
  475. data/spec/graphql/backtrace_spec.rb +0 -206
  476. data/spec/graphql/base_type_spec.rb +0 -171
  477. data/spec/graphql/boolean_type_spec.rb +0 -21
  478. data/spec/graphql/compatibility/execution_specification_spec.rb +0 -4
  479. data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +0 -4
  480. data/spec/graphql/compatibility/query_parser_specification_spec.rb +0 -6
  481. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +0 -6
  482. data/spec/graphql/define/assign_argument_spec.rb +0 -61
  483. data/spec/graphql/define/instance_definable_spec.rb +0 -203
  484. data/spec/graphql/directive/skip_directive_spec.rb +0 -9
  485. data/spec/graphql/directive_spec.rb +0 -295
  486. data/spec/graphql/enum_type_spec.rb +0 -158
  487. data/spec/graphql/execution/execute_spec.rb +0 -303
  488. data/spec/graphql/execution/instrumentation_spec.rb +0 -184
  489. data/spec/graphql/execution/interpreter_spec.rb +0 -485
  490. data/spec/graphql/execution/lazy/lazy_method_map_spec.rb +0 -57
  491. data/spec/graphql/execution/lazy_spec.rb +0 -247
  492. data/spec/graphql/execution/lookahead_spec.rb +0 -390
  493. data/spec/graphql/execution/multiplex_spec.rb +0 -211
  494. data/spec/graphql/execution/typecast_spec.rb +0 -47
  495. data/spec/graphql/execution_error_spec.rb +0 -325
  496. data/spec/graphql/field_spec.rb +0 -246
  497. data/spec/graphql/float_type_spec.rb +0 -16
  498. data/spec/graphql/function_spec.rb +0 -152
  499. data/spec/graphql/id_type_spec.rb +0 -33
  500. data/spec/graphql/input_object_type_spec.rb +0 -25
  501. data/spec/graphql/int_type_spec.rb +0 -35
  502. data/spec/graphql/interface_type_spec.rb +0 -196
  503. data/spec/graphql/internal_representation/print_spec.rb +0 -41
  504. data/spec/graphql/internal_representation/rewrite_spec.rb +0 -376
  505. data/spec/graphql/introspection/directive_type_spec.rb +0 -61
  506. data/spec/graphql/introspection/input_value_type_spec.rb +0 -144
  507. data/spec/graphql/introspection/introspection_query_spec.rb +0 -59
  508. data/spec/graphql/introspection/schema_type_spec.rb +0 -56
  509. data/spec/graphql/introspection/type_type_spec.rb +0 -155
  510. data/spec/graphql/language/block_string_spec.rb +0 -70
  511. data/spec/graphql/language/definition_slice_spec.rb +0 -226
  512. data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
  513. data/spec/graphql/language/equality_spec.rb +0 -84
  514. data/spec/graphql/language/generation_spec.rb +0 -38
  515. data/spec/graphql/language/lexer_spec.rb +0 -135
  516. data/spec/graphql/language/nodes_spec.rb +0 -67
  517. data/spec/graphql/language/parser_spec.rb +0 -183
  518. data/spec/graphql/language/printer_spec.rb +0 -215
  519. data/spec/graphql/language/visitor_spec.rb +0 -419
  520. data/spec/graphql/list_type_spec.rb +0 -57
  521. data/spec/graphql/non_null_type_spec.rb +0 -48
  522. data/spec/graphql/object_type_spec.rb +0 -197
  523. data/spec/graphql/query/arguments_spec.rb +0 -346
  524. data/spec/graphql/query/context_spec.rb +0 -292
  525. data/spec/graphql/query/executor_spec.rb +0 -341
  526. data/spec/graphql/query/literal_input_spec.rb +0 -91
  527. data/spec/graphql/query/result_spec.rb +0 -29
  528. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -109
  529. data/spec/graphql/query_spec.rb +0 -800
  530. data/spec/graphql/rake_task_spec.rb +0 -59
  531. data/spec/graphql/scalar_type_spec.rb +0 -66
  532. data/spec/graphql/schema/argument_spec.rb +0 -152
  533. data/spec/graphql/schema/build_from_definition_spec.rb +0 -1187
  534. data/spec/graphql/schema/catchall_middleware_spec.rb +0 -35
  535. data/spec/graphql/schema/directive/feature_spec.rb +0 -81
  536. data/spec/graphql/schema/directive/transform_spec.rb +0 -39
  537. data/spec/graphql/schema/enum_spec.rb +0 -83
  538. data/spec/graphql/schema/enum_value_spec.rb +0 -24
  539. data/spec/graphql/schema/field_extension_spec.rb +0 -137
  540. data/spec/graphql/schema/field_spec.rb +0 -301
  541. data/spec/graphql/schema/finder_spec.rb +0 -135
  542. data/spec/graphql/schema/input_object_spec.rb +0 -347
  543. data/spec/graphql/schema/instrumentation_spec.rb +0 -43
  544. data/spec/graphql/schema/interface_spec.rb +0 -215
  545. data/spec/graphql/schema/introspection_system_spec.rb +0 -56
  546. data/spec/graphql/schema/list_spec.rb +0 -46
  547. data/spec/graphql/schema/loader_spec.rb +0 -286
  548. data/spec/graphql/schema/member/accepts_definition_spec.rb +0 -115
  549. data/spec/graphql/schema/member/build_type_spec.rb +0 -63
  550. data/spec/graphql/schema/member/scoped_spec.rb +0 -217
  551. data/spec/graphql/schema/member/type_system_helpers_spec.rb +0 -63
  552. data/spec/graphql/schema/middleware_chain_spec.rb +0 -57
  553. data/spec/graphql/schema/mutation_spec.rb +0 -150
  554. data/spec/graphql/schema/non_null_spec.rb +0 -46
  555. data/spec/graphql/schema/object_spec.rb +0 -315
  556. data/spec/graphql/schema/printer_spec.rb +0 -869
  557. data/spec/graphql/schema/relay_classic_mutation_spec.rb +0 -252
  558. data/spec/graphql/schema/rescue_middleware_spec.rb +0 -88
  559. data/spec/graphql/schema/resolver_spec.rb +0 -714
  560. data/spec/graphql/schema/scalar_spec.rb +0 -101
  561. data/spec/graphql/schema/subscription_spec.rb +0 -440
  562. data/spec/graphql/schema/timeout_middleware_spec.rb +0 -188
  563. data/spec/graphql/schema/traversal_spec.rb +0 -222
  564. data/spec/graphql/schema/type_expression_spec.rb +0 -39
  565. data/spec/graphql/schema/union_spec.rb +0 -72
  566. data/spec/graphql/schema/unique_within_type_spec.rb +0 -44
  567. data/spec/graphql/schema/validation_spec.rb +0 -355
  568. data/spec/graphql/schema/warden_spec.rb +0 -926
  569. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -413
  570. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +0 -44
  571. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -112
  572. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -35
  573. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -42
  574. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -167
  575. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -66
  576. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -740
  577. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +0 -28
  578. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -52
  579. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -42
  580. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -123
  581. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +0 -24
  582. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -56
  583. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -61
  584. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +0 -39
  585. data/spec/graphql/static_validation/rules/no_definitions_are_present_spec.rb +0 -62
  586. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +0 -82
  587. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -73
  588. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +0 -86
  589. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +0 -34
  590. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +0 -188
  591. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -196
  592. data/spec/graphql/static_validation/rules/variable_names_are_unique_spec.rb +0 -23
  593. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -236
  594. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -78
  595. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -81
  596. data/spec/graphql/static_validation/type_stack_spec.rb +0 -29
  597. data/spec/graphql/static_validation/validator_spec.rb +0 -204
  598. data/spec/graphql/string_type_spec.rb +0 -80
  599. data/spec/graphql/subscriptions/serialize_spec.rb +0 -49
  600. data/spec/graphql/subscriptions_spec.rb +0 -540
  601. data/spec/graphql/tracing/new_relic_tracing_spec.rb +0 -84
  602. data/spec/graphql/tracing/platform_tracing_spec.rb +0 -141
  603. data/spec/graphql/tracing/prometheus_tracing_spec.rb +0 -42
  604. data/spec/graphql/tracing/scout_tracing_spec.rb +0 -17
  605. data/spec/graphql/tracing/skylight_tracing_spec.rb +0 -63
  606. data/spec/graphql/tracing_spec.rb +0 -52
  607. data/spec/graphql/types/big_int_spec.rb +0 -24
  608. data/spec/graphql/types/iso_8601_date_time_spec.rb +0 -137
  609. data/spec/graphql/types/relay/base_edge_spec.rb +0 -33
  610. data/spec/graphql/union_type_spec.rb +0 -211
  611. data/spec/graphql/upgrader/member_spec.rb +0 -583
  612. data/spec/graphql/upgrader/schema_spec.rb +0 -82
  613. data/spec/integration/mongoid/graphql/relay/mongo_relation_connection_spec.rb +0 -528
  614. data/spec/integration/mongoid/spec_helper.rb +0 -2
  615. data/spec/integration/mongoid/star_trek/data.rb +0 -126
  616. data/spec/integration/mongoid/star_trek/schema.rb +0 -425
  617. data/spec/integration/rails/data.rb +0 -110
  618. data/spec/integration/rails/generators/base_generator_test.rb +0 -7
  619. data/spec/integration/rails/generators/graphql/enum_generator_spec.rb +0 -30
  620. data/spec/integration/rails/generators/graphql/install_generator_spec.rb +0 -218
  621. data/spec/integration/rails/generators/graphql/interface_generator_spec.rb +0 -34
  622. data/spec/integration/rails/generators/graphql/loader_generator_spec.rb +0 -59
  623. data/spec/integration/rails/generators/graphql/mutation_generator_spec.rb +0 -71
  624. data/spec/integration/rails/generators/graphql/object_generator_spec.rb +0 -54
  625. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +0 -28
  626. data/spec/integration/rails/generators/graphql/union_generator_spec.rb +0 -67
  627. data/spec/integration/rails/graphql/input_object_type_spec.rb +0 -364
  628. data/spec/integration/rails/graphql/query/variables_spec.rb +0 -375
  629. data/spec/integration/rails/graphql/relay/array_connection_spec.rb +0 -290
  630. data/spec/integration/rails/graphql/relay/base_connection_spec.rb +0 -101
  631. data/spec/integration/rails/graphql/relay/connection_instrumentation_spec.rb +0 -80
  632. data/spec/integration/rails/graphql/relay/connection_resolve_spec.rb +0 -79
  633. data/spec/integration/rails/graphql/relay/connection_type_spec.rb +0 -106
  634. data/spec/integration/rails/graphql/relay/edge_spec.rb +0 -10
  635. data/spec/integration/rails/graphql/relay/mutation_spec.rb +0 -387
  636. data/spec/integration/rails/graphql/relay/node_spec.rb +0 -263
  637. data/spec/integration/rails/graphql/relay/page_info_spec.rb +0 -111
  638. data/spec/integration/rails/graphql/relay/range_add_spec.rb +0 -117
  639. data/spec/integration/rails/graphql/relay/relation_connection_spec.rb +0 -837
  640. data/spec/integration/rails/graphql/schema_spec.rb +0 -489
  641. data/spec/integration/rails/graphql/tracing/active_support_notifications_tracing_spec.rb +0 -62
  642. data/spec/integration/rails/spec_helper.rb +0 -25
  643. data/spec/integration/tmp/app/graphql/types/bird_type.rb +0 -7
  644. data/spec/spec_helper.rb +0 -116
  645. data/spec/support/dummy/data.rb +0 -45
  646. data/spec/support/dummy/schema.rb +0 -511
  647. data/spec/support/error_bubbling_helpers.rb +0 -23
  648. data/spec/support/global_id.rb +0 -23
  649. data/spec/support/jazz.rb +0 -772
  650. data/spec/support/lazy_helpers.rb +0 -192
  651. data/spec/support/magic_cards/schema.graphql +0 -33
  652. data/spec/support/minimum_input_object.rb +0 -21
  653. data/spec/support/new_relic.rb +0 -27
  654. data/spec/support/parser/filename_example.graphql +0 -5
  655. data/spec/support/parser/filename_example_error_1.graphql +0 -4
  656. data/spec/support/parser/filename_example_error_2.graphql +0 -5
  657. data/spec/support/skylight.rb +0 -39
  658. data/spec/support/star_wars/schema.rb +0 -465
  659. data/spec/support/static_validation_helpers.rb +0 -32
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ # This plugin will stop resolving new fields after `max_seconds` have elapsed.
6
+ # After the time has passed, any remaining fields will be `nil`, with errors added
7
+ # to the `errors` key. Any already-resolved fields will be in the `data` key, so
8
+ # you'll get a partial response.
9
+ #
10
+ # You can subclass `GraphQL::Schema::Timeout` and override `max_seconds` and/or `handle_timeout`
11
+ # to provide custom logic when a timeout error occurs.
12
+ #
13
+ # Note that this will stop a query _in between_ field resolutions, but
14
+ # it doesn't interrupt long-running `resolve` functions. Be sure to use
15
+ # timeout options for external connections. For more info, see
16
+ # www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/
17
+ #
18
+ # @example Stop resolving fields after 2 seconds
19
+ # class MySchema < GraphQL::Schema
20
+ # use GraphQL::Schema::Timeout, max_seconds: 2
21
+ # end
22
+ #
23
+ # @example Notifying Bugsnag and logging a timeout
24
+ # class MyTimeout < GraphQL::Schema::Timeout
25
+ # def handle_timeout(error, query)
26
+ # Rails.logger.warn("GraphQL Timeout: #{error.message}: #{query.query_string}")
27
+ # Bugsnag.notify(error, {query_string: query.query_string})
28
+ # end
29
+ # end
30
+ #
31
+ # class MySchema < GraphQL::Schema
32
+ # use MyTimeout, max_seconds: 2
33
+ # end
34
+ #
35
+ class Timeout
36
+ def self.use(schema, **options)
37
+ tracer = new(**options)
38
+ schema.tracer(tracer)
39
+ end
40
+
41
+ # @param max_seconds [Numeric] how many seconds the query should be allowed to resolve new fields
42
+ def initialize(max_seconds:)
43
+ @max_seconds = max_seconds
44
+ end
45
+
46
+ def trace(key, data)
47
+ case key
48
+ when 'execute_multiplex'
49
+ data.fetch(:multiplex).queries.each do |query|
50
+ timeout_duration_s = max_seconds(query)
51
+ timeout_state = if timeout_duration_s == false
52
+ # if the method returns `false`, don't apply a timeout
53
+ false
54
+ else
55
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
56
+ timeout_at = now + (max_seconds(query) * 1000)
57
+ {
58
+ timeout_at: timeout_at,
59
+ timed_out: false
60
+ }
61
+ end
62
+ query.context.namespace(self.class)[:state] = timeout_state
63
+ end
64
+
65
+ yield
66
+ when 'execute_field', 'execute_field_lazy'
67
+ query_context = data[:context] || data[:query].context
68
+ timeout_state = query_context.namespace(self.class).fetch(:state)
69
+ # If the `:state` is `false`, then `max_seconds(query)` opted out of timeout for this query.
70
+ if timeout_state != false && Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) > timeout_state.fetch(:timeout_at)
71
+ error = if data[:context]
72
+ GraphQL::Schema::Timeout::TimeoutError.new(query_context.parent_type, query_context.field)
73
+ else
74
+ field = data.fetch(:field)
75
+ GraphQL::Schema::Timeout::TimeoutError.new(field.owner, field)
76
+ end
77
+
78
+ # Only invoke the timeout callback for the first timeout
79
+ if !timeout_state[:timed_out]
80
+ timeout_state[:timed_out] = true
81
+ handle_timeout(error, query_context.query)
82
+ end
83
+
84
+ error
85
+ else
86
+ yield
87
+ end
88
+ else
89
+ yield
90
+ end
91
+ end
92
+
93
+ # Called at the start of each query.
94
+ # The default implementation returns the `max_seconds:` value from installing this plugin.
95
+ #
96
+ # @param query [GraphQL::Query] The query that's about to run
97
+ # @return [Integer, false] The number of seconds after which to interrupt query execution and call {#handle_error}, or `false` to bypass the timeout.
98
+ def max_seconds(query)
99
+ @max_seconds
100
+ end
101
+
102
+ # Invoked when a query times out.
103
+ # @param error [GraphQL::Schema::Timeout::TimeoutError]
104
+ # @param query [GraphQL::Error]
105
+ def handle_timeout(error, query)
106
+ # override to do something interesting
107
+ end
108
+
109
+ # This error is raised when a query exceeds `max_seconds`.
110
+ # Since it's a child of {GraphQL::ExecutionError},
111
+ # its message will be added to the response's `errors` key.
112
+ #
113
+ # To raise an error that will stop query resolution, use a custom block
114
+ # to take this error and raise a new one which _doesn't_ descend from {GraphQL::ExecutionError},
115
+ # such as `RuntimeError`.
116
+ class TimeoutError < GraphQL::ExecutionError
117
+ def initialize(parent_type, field)
118
+ super("Timeout on #{parent_type.graphql_name}.#{field.graphql_name}")
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -23,21 +23,24 @@ module GraphQL
23
23
  # Bugsnag.notify(timeout_error, {query_string: query_ctx.query.query_string})
24
24
  # end
25
25
  #
26
+ # @api deprecated
27
+ # @see Schema::Timeout
26
28
  class TimeoutMiddleware
27
29
  # @param max_seconds [Numeric] how many seconds the query should be allowed to resolve new fields
28
30
  def initialize(max_seconds:, context_key: nil, &block)
29
31
  @max_seconds = max_seconds
30
32
  if context_key
31
- warn("TimeoutMiddleware's `context_key` is ignored, timeout data is now stored in isolated storage")
33
+ GraphQL::Deprecation.warn("TimeoutMiddleware's `context_key` is ignored, timeout data is now stored in isolated storage")
32
34
  end
33
35
  @error_handler = block
34
36
  end
35
37
 
36
38
  def call(parent_type, parent_object, field_definition, field_args, query_context)
37
39
  ns = query_context.namespace(self.class)
38
- timeout_at = ns[:timeout_at] ||= Time.now + @max_seconds
40
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
41
+ timeout_at = ns[:timeout_at] ||= now + @max_seconds
39
42
 
40
- if timeout_at < Time.now
43
+ if timeout_at < now
41
44
  on_timeout(parent_type, parent_object, field_definition, field_args, query_context)
42
45
  else
43
46
  yield
@@ -113,7 +113,7 @@ Some late-bound types couldn't be resolved:
113
113
  # Find the starting points, then visit them
114
114
  visit_roots = [member.query, member.mutation, member.subscription]
115
115
  if @introspection
116
- introspection_types = schema.introspection_system.object_types
116
+ introspection_types = schema.introspection_system.types.values
117
117
  visit_roots.concat(introspection_types)
118
118
  if member.query
119
119
  member.introspection_system.entry_points.each do |introspection_field|
@@ -173,7 +173,7 @@ Some late-bound types couldn't be resolved:
173
173
  end
174
174
  when Class
175
175
  if member.respond_to?(:graphql_definition)
176
- graphql_member = member.graphql_definition
176
+ graphql_member = member.graphql_definition(silence_deprecation_warning: true)
177
177
  visit(schema, graphql_member, context_description)
178
178
  else
179
179
  raise GraphQL::Schema::InvalidTypeError.new("Unexpected traversal member: #{member} (#{member.class.name})")
@@ -5,29 +5,37 @@ module GraphQL
5
5
  module TypeExpression
6
6
  # Fetch a type from a type map by its AST specification.
7
7
  # Return `nil` if not found.
8
- # @param types [GraphQL::Schema::TypeMap]
8
+ # @param type_owner [#get_type] A thing for looking up types by name
9
9
  # @param ast_node [GraphQL::Language::Nodes::AbstractNode]
10
- # @return [GraphQL::BaseType, nil]
11
- def self.build_type(types, ast_node)
10
+ # @return [Class, GraphQL::Schema::NonNull, GraphQL::Schema:List]
11
+ def self.build_type(type_owner, ast_node)
12
12
  case ast_node
13
13
  when GraphQL::Language::Nodes::TypeName
14
- types.fetch(ast_node.name, nil)
14
+ type_owner.get_type(ast_node.name) # rubocop:disable Development/ContextIsPassedCop -- this is a `context` or `warden`, it's already query-aware
15
15
  when GraphQL::Language::Nodes::NonNullType
16
16
  ast_inner_type = ast_node.of_type
17
- inner_type = build_type(types, ast_inner_type)
18
- wrap_type(inner_type, GraphQL::NonNullType)
17
+ inner_type = build_type(type_owner, ast_inner_type)
18
+ wrap_type(inner_type, :to_non_null_type)
19
19
  when GraphQL::Language::Nodes::ListType
20
20
  ast_inner_type = ast_node.of_type
21
- inner_type = build_type(types, ast_inner_type)
22
- wrap_type(inner_type, GraphQL::ListType)
21
+ inner_type = build_type(type_owner, ast_inner_type)
22
+ wrap_type(inner_type, :to_list_type)
23
+ else
24
+ raise "Invariant: unexpected type from ast: #{ast_node.inspect}"
23
25
  end
24
26
  end
25
27
 
26
- def self.wrap_type(type, wrapper)
27
- if type.nil?
28
- nil
29
- else
30
- wrapper.new(of_type: type)
28
+ class << self
29
+ private
30
+
31
+ def wrap_type(type, wrapper_method)
32
+ if type.nil?
33
+ nil
34
+ elsif wrapper_method == :to_list_type || wrapper_method == :to_non_null_type
35
+ type.public_send(wrapper_method)
36
+ else
37
+ raise ArgumentError, "Unexpected wrapper method: #{wrapper_method.inspect}"
38
+ end
31
39
  end
32
40
  end
33
41
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ # This class joins an object type to an abstract type (interface or union) of which
6
+ # it is a member.
7
+ class TypeMembership
8
+ # @return [Class<GraphQL::Schema::Object>]
9
+ attr_accessor :object_type
10
+
11
+ # @return [Class<GraphQL::Schema::Union>, Module<GraphQL::Schema::Interface>]
12
+ attr_reader :abstract_type
13
+
14
+ # Called when an object is hooked up to an abstract type, such as {Schema::Union.possible_types}
15
+ # or {Schema::Object.implements} (for interfaces).
16
+ #
17
+ # @param abstract_type [Class<GraphQL::Schema::Union>, Module<GraphQL::Schema::Interface>]
18
+ # @param object_type [Class<GraphQL::Schema::Object>]
19
+ # @param options [Hash] Any options passed to `.possible_types` or `.implements`
20
+ def initialize(abstract_type, object_type, **options)
21
+ @abstract_type = abstract_type
22
+ @object_type = object_type
23
+ @options = options
24
+ end
25
+
26
+ # @return [Boolean] if false, {#object_type} will be treated as _not_ a member of {#abstract_type}
27
+ def visible?(ctx)
28
+ warden = Warden.from_context(ctx)
29
+ (@object_type.respond_to?(:visible?) ? warden.visible_type?(@object_type, ctx) : true) &&
30
+ (@abstract_type.respond_to?(:visible?) ? warden.visible_type?(@abstract_type, ctx) : true)
31
+ end
32
+
33
+ def graphql_name
34
+ "#{@object_type.graphql_name}.#{@abstract_type.kind.interface? ? "implements" : "belongsTo" }.#{@abstract_type.graphql_name}"
35
+ end
36
+
37
+ def path
38
+ graphql_name
39
+ end
40
+
41
+ def inspect
42
+ "#<#{self.class} #{@object_type.inspect} => #{@abstract_type.inspect}>"
43
+ end
44
+
45
+ alias :type_class :itself
46
+ end
47
+ end
48
+ end
@@ -3,23 +3,44 @@ module GraphQL
3
3
  class Schema
4
4
  class Union < GraphQL::Schema::Member
5
5
  extend GraphQL::Schema::Member::AcceptsDefinition
6
+ extend GraphQL::Schema::Member::HasUnresolvedTypeError
6
7
 
7
8
  class << self
8
- def possible_types(*types)
9
+ def inherited(child_class)
10
+ add_unresolved_type_error(child_class)
11
+ super
12
+ end
13
+
14
+ def possible_types(*types, context: GraphQL::Query::NullContext, **options)
9
15
  if types.any?
10
- @possible_types = types
16
+ types.each do |t|
17
+ assert_valid_union_member(t)
18
+ type_memberships << type_membership_class.new(self, t, **options)
19
+ end
11
20
  else
12
- all_possible_types = @possible_types || []
13
- all_possible_types += super if defined?(super)
14
- all_possible_types.uniq
21
+ visible_types = []
22
+ warden = Warden.from_context(context)
23
+ type_memberships.each do |type_membership|
24
+ if warden.visible_type_membership?(type_membership, context)
25
+ visible_types << type_membership.object_type
26
+ end
27
+ end
28
+ visible_types
15
29
  end
16
30
  end
17
31
 
32
+ def all_possible_types
33
+ type_memberships.map(&:object_type)
34
+ end
35
+
36
+ prepend GraphQL::Schema::Member::CachedGraphQLDefinition::DeprecatedToGraphQL
37
+
18
38
  def to_graphql
19
39
  type_defn = GraphQL::UnionType.new
20
40
  type_defn.name = graphql_name
21
41
  type_defn.description = description
22
- type_defn.possible_types = possible_types
42
+ type_defn.ast_node = ast_node
43
+ type_defn.type_memberships = type_memberships
23
44
  if respond_to?(:resolve_type)
24
45
  type_defn.resolve_type = method(:resolve_type)
25
46
  end
@@ -27,9 +48,49 @@ module GraphQL
27
48
  type_defn
28
49
  end
29
50
 
51
+ def type_membership_class(membership_class = nil)
52
+ if membership_class
53
+ @type_membership_class = membership_class
54
+ else
55
+ @type_membership_class || find_inherited_value(:type_membership_class, GraphQL::Schema::TypeMembership)
56
+ end
57
+ end
58
+
30
59
  def kind
31
60
  GraphQL::TypeKinds::UNION
32
61
  end
62
+
63
+ def type_memberships
64
+ @type_memberships ||= []
65
+ end
66
+
67
+ # Update a type membership whose `.object_type` is a string or late-bound type
68
+ # so that the type membership's `.object_type` is the given `object_type`.
69
+ # (This is used for updating the union after the schema as lazily loaded the union member.)
70
+ # @api private
71
+ def assign_type_membership_object_type(object_type)
72
+ assert_valid_union_member(object_type)
73
+ type_memberships.each { |tm|
74
+ possible_type = tm.object_type
75
+ if possible_type.is_a?(String) && (possible_type == object_type.name)
76
+ # This is a match of Ruby class names, not graphql names,
77
+ # since strings are used to refer to constants.
78
+ tm.object_type = object_type
79
+ elsif possible_type.is_a?(LateBoundType) && possible_type.graphql_name == object_type.graphql_name
80
+ tm.object_type = object_type
81
+ end
82
+ }
83
+ nil
84
+ end
85
+
86
+ private
87
+
88
+ def assert_valid_union_member(type_defn)
89
+ if type_defn.is_a?(Module) && !type_defn.is_a?(Class)
90
+ # it's an interface type, defined as a module
91
+ raise ArgumentError, "Union possible_types can only be object types (not interface types), remove #{type_defn.graphql_name} (#{type_defn.inspect})"
92
+ end
93
+ end
33
94
  end
34
95
  end
35
96
  end
@@ -27,8 +27,7 @@ module GraphQL
27
27
  # @param node_id [String] A unique ID generated by {.encode}
28
28
  # @return [Array<(String, String)>] The type name & value passed to {.encode}
29
29
  def decode(node_id, separator: self.default_id_separator)
30
- # urlsafe_decode64 is for forward compatibility
31
- Base64Bp.urlsafe_decode64(node_id).split(separator, 2)
30
+ GraphQL::Schema::Base64Encoder.decode(node_id).split(separator, 2)
32
31
  end
33
32
  end
34
33
  end
@@ -6,6 +6,8 @@ module GraphQL
6
6
  # Its {RULES} contain objects that respond to `#call(type)`. Rules are
7
7
  # looked up for given types (by class ancestry), then applied to
8
8
  # the object until an error is returned.
9
+ #
10
+ # Remove this in GraphQL-Ruby 2.0 when schema instances are removed.
9
11
  class Validation
10
12
  # Lookup the rules for `object` based on its class,
11
13
  # Then returns an error message or `nil`
@@ -77,6 +79,18 @@ module GraphQL
77
79
  }
78
80
  end
79
81
 
82
+ def self.count_at_least(item_name, minimum_count, get_items_proc)
83
+ ->(type) {
84
+ items = get_items_proc.call(type)
85
+
86
+ if items.size < minimum_count
87
+ "#{type.name} must define at least #{minimum_count} #{item_name}. #{items.size} defined."
88
+ else
89
+ nil
90
+ end
91
+ }
92
+ end
93
+
80
94
  def self.assert_named_items_are_valid(item_name, get_items_proc)
81
95
  ->(type) {
82
96
  items = get_items_proc.call(type)
@@ -92,7 +106,9 @@ module GraphQL
92
106
  }
93
107
  end
94
108
 
109
+ HAS_AT_LEAST_ONE_FIELD = Rules.count_at_least("field", 1, ->(type) { type.all_fields })
95
110
  FIELDS_ARE_VALID = Rules.assert_named_items_are_valid("field", ->(type) { type.all_fields })
111
+ HAS_AT_LEAST_ONE_ARGUMENT = Rules.count_at_least("argument", 1, ->(type) { type.arguments })
96
112
 
97
113
  HAS_ONE_OR_MORE_POSSIBLE_TYPES = ->(type) {
98
114
  type.possible_types.length >= 1 ? nil : "must have at least one possible type"
@@ -104,10 +120,6 @@ module GraphQL
104
120
  ARGUMENTS_ARE_VALID = Rules.assert_named_items_are_valid("argument", ->(type) { type.arguments.values })
105
121
 
106
122
  DEFAULT_VALUE_IS_VALID_FOR_TYPE = ->(type) {
107
- if !type.default_value.nil? && type.type.is_a?(NonNullType)
108
- return %Q(Variable #{type.name} of type "#{type.type}" is required and will not use the default value. Perhaps you meant to use type "#{type.type.of_type}".)
109
- end
110
-
111
123
  if !type.default_value.nil?
112
124
  coerced_value = begin
113
125
  type.type.coerce_isolated_result(type.default_value)
@@ -123,9 +135,15 @@ module GraphQL
123
135
  end
124
136
  }
125
137
 
138
+ DEPRECATED_ARGUMENTS_ARE_OPTIONAL = ->(argument) {
139
+ if argument.deprecation_reason && argument.type.non_null?
140
+ "must be optional because it's deprecated"
141
+ end
142
+ }
143
+
126
144
  TYPE_IS_VALID_INPUT_TYPE = ->(type) {
127
145
  outer_type = type.type
128
- inner_type = outer_type.is_a?(GraphQL::BaseType) ? outer_type.unwrap : nil
146
+ inner_type = outer_type.respond_to?(:unwrap) ? outer_type.unwrap : nil
129
147
 
130
148
  case inner_type
131
149
  when GraphQL::ScalarType, GraphQL::InputObjectType, GraphQL::EnumType
@@ -144,7 +162,7 @@ module GraphQL
144
162
  }
145
163
 
146
164
  SCHEMA_CAN_FETCH_IDS = ->(schema) {
147
- has_node_field = schema.query && schema.query.all_fields.any?(&:relay_node_field)
165
+ has_node_field = schema.query && schema.query.fields.each_value.any?(&:relay_node_field)
148
166
  if has_node_field && schema.object_from_id_proc.nil?
149
167
  "schema contains `node(id:...)` field, so you must define a `object_from_id -> (id, ctx) { ... }` function"
150
168
  else
@@ -185,7 +203,7 @@ module GraphQL
185
203
  RESERVED_TYPE_NAME = ->(type) {
186
204
  if type.name.start_with?('__') && !type.introspection?
187
205
  # TODO: make this a hard failure in a later version
188
- warn("Name #{type.name.inspect} must not begin with \"__\", which is reserved by GraphQL introspection.")
206
+ GraphQL::Deprecation.warn("Name #{type.name.inspect} must not begin with \"__\", which is reserved by GraphQL introspection.")
189
207
  nil
190
208
  else
191
209
  # ok name
@@ -195,7 +213,7 @@ module GraphQL
195
213
  RESERVED_NAME = ->(named_thing) {
196
214
  if named_thing.name.start_with?('__')
197
215
  # TODO: make this a hard failure in a later version
198
- warn("Name #{named_thing.name.inspect} must not begin with \"__\", which is reserved by GraphQL introspection.")
216
+ GraphQL::Deprecation.warn("Name #{named_thing.name.inspect} must not begin with \"__\", which is reserved by GraphQL introspection.")
199
217
  nil
200
218
  else
201
219
  # no worries
@@ -255,8 +273,10 @@ module GraphQL
255
273
  Rules::NAME_IS_STRING,
256
274
  Rules::RESERVED_NAME,
257
275
  Rules::DESCRIPTION_IS_STRING_OR_NIL,
276
+ Rules.assert_property(:deprecation_reason, String, NilClass),
258
277
  Rules::TYPE_IS_VALID_INPUT_TYPE,
259
278
  Rules::DEFAULT_VALUE_IS_VALID_FOR_TYPE,
279
+ Rules::DEPRECATED_ARGUMENTS_ARE_OPTIONAL,
260
280
  ],
261
281
  GraphQL::BaseType => [
262
282
  Rules::NAME_IS_STRING,
@@ -264,11 +284,13 @@ module GraphQL
264
284
  Rules::DESCRIPTION_IS_STRING_OR_NIL,
265
285
  ],
266
286
  GraphQL::ObjectType => [
287
+ Rules::HAS_AT_LEAST_ONE_FIELD,
267
288
  Rules.assert_property_list_of(:interfaces, GraphQL::InterfaceType),
268
289
  Rules::FIELDS_ARE_VALID,
269
290
  Rules::INTERFACES_ARE_IMPLEMENTED,
270
291
  ],
271
292
  GraphQL::InputObjectType => [
293
+ Rules::HAS_AT_LEAST_ONE_ARGUMENT,
272
294
  Rules::ARGUMENTS_ARE_STRING_TO_ARGUMENT,
273
295
  Rules::ARGUMENTS_ARE_VALID,
274
296
  ],
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Validator
6
+ # Use this to specifically reject values that respond to `.blank?` and respond truthy for that method.
7
+ #
8
+ # @example Require a non-empty string for an argument
9
+ # argument :name, String, required: true, validate: { allow_blank: false }
10
+ class AllowBlankValidator < Validator
11
+ def initialize(allow_blank_positional, allow_blank: nil, message: "%{validated} can't be blank", **default_options)
12
+ @message = message
13
+ super(**default_options)
14
+ @allow_blank = allow_blank.nil? ? allow_blank_positional : allow_blank
15
+ end
16
+
17
+ def validate(_object, _context, value)
18
+ if value.respond_to?(:blank?) && value.blank?
19
+ if (value.nil? && @allow_null) || @allow_blank
20
+ # pass
21
+ else
22
+ @message
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Validator
6
+ # Use this to specifically reject or permit `nil` values (given as `null` from GraphQL).
7
+ #
8
+ # @example require a non-null value for an argument if it is provided
9
+ # argument :name, String, required: false, validates: { allow_null: false }
10
+ class AllowNullValidator < Validator
11
+ MESSAGE = "%{validated} can't be null"
12
+ def initialize(allow_null_positional, allow_null: nil, message: MESSAGE, **default_options)
13
+ @message = message
14
+ super(**default_options)
15
+ @allow_null = allow_null.nil? ? allow_null_positional : allow_null
16
+ end
17
+
18
+ def validate(_object, _context, value)
19
+ if value.nil? && !@allow_null
20
+ @message
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Validator
6
+ # Use this to specifically reject values from an argument.
7
+ #
8
+ # @example disallow certain values
9
+ #
10
+ # argument :favorite_non_prime, Integer, required: true,
11
+ # validates: { exclusion: { in: [2, 3, 5, 7, ... ]} }
12
+ #
13
+ class ExclusionValidator < Validator
14
+ # @param message [String]
15
+ # @param in [Array] The values to reject
16
+ def initialize(message: "%{validated} is reserved", in:, **default_options)
17
+ # `in` is a reserved word, so work around that
18
+ @in_list = binding.local_variable_get(:in)
19
+ @message = message
20
+ super(**default_options)
21
+ end
22
+
23
+ def validate(_object, _context, value)
24
+ if permitted_empty_value?(value)
25
+ # pass
26
+ elsif @in_list.include?(value)
27
+ @message
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Validator
6
+ # Use this to assert that string values match (or don't match) the given RegExp.
7
+ #
8
+ # @example requiring input to match a pattern
9
+ #
10
+ # argument :handle, String, required: true,
11
+ # validates: { format: { with: /\A[a-z0-9_]+\Z/ } }
12
+ #
13
+ # @example reject inputs that match a pattern
14
+ #
15
+ # argument :word_that_doesnt_begin_with_a_vowel, String, required: true,
16
+ # validates: { format: { without: /\A[aeiou]/ } }
17
+ #
18
+ # # It's pretty hard to come up with a legitimate use case for `without:`
19
+ #
20
+ class FormatValidator < Validator
21
+ # @param with [RegExp, nil]
22
+ # @param without [Regexp, nil]
23
+ # @param message [String]
24
+ def initialize(
25
+ with: nil,
26
+ without: nil,
27
+ message: "%{validated} is invalid",
28
+ **default_options
29
+ )
30
+ @with_pattern = with
31
+ @without_pattern = without
32
+ @message = message
33
+ super(**default_options)
34
+ end
35
+
36
+ def validate(_object, _context, value)
37
+ if permitted_empty_value?(value)
38
+ # Do nothing
39
+ elsif value.nil? ||
40
+ (@with_pattern && !value.match?(@with_pattern)) ||
41
+ (@without_pattern && value.match?(@without_pattern))
42
+ @message
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ class Validator
6
+ # You can use this to allow certain values for an argument.
7
+ #
8
+ # Usually, a {GraphQL::Schema::Enum} is better for this, because it's self-documenting.
9
+ #
10
+ # @example only allow certain values for an argument
11
+ #
12
+ # argument :favorite_prime, Integer, required: true,
13
+ # validates: { inclusion: { in: [2, 3, 5, 7, 11, ... ] } }
14
+ #
15
+ class InclusionValidator < Validator
16
+ # @param message [String]
17
+ # @param in [Array] The values to allow
18
+ def initialize(in:, message: "%{validated} is not included in the list", **default_options)
19
+ # `in` is a reserved word, so work around that
20
+ @in_list = binding.local_variable_get(:in)
21
+ @message = message
22
+ super(**default_options)
23
+ end
24
+
25
+ def validate(_object, _context, value)
26
+ if permitted_empty_value?(value)
27
+ # pass
28
+ elsif !@in_list.include?(value)
29
+ @message
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end