graphql 1.10.2 → 2.0.21

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 (402) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +21 -10
  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/{templates → install/templates}/base_mutation.erb +2 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
  9. data/lib/generators/graphql/install_generator.rb +45 -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 +49 -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 +2 -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 +2 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  28. data/lib/generators/graphql/templates/base_object.erb +2 -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 +16 -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 +24 -33
  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/ast/field_usage.rb +30 -1
  49. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
  50. data/lib/graphql/analysis/ast/query_complexity.rb +125 -117
  51. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  52. data/lib/graphql/analysis/ast/visitor.rb +52 -36
  53. data/lib/graphql/analysis/ast.rb +7 -8
  54. data/lib/graphql/analysis.rb +0 -7
  55. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  56. data/lib/graphql/backtrace/table.rb +31 -18
  57. data/lib/graphql/backtrace/trace.rb +96 -0
  58. data/lib/graphql/backtrace/traced_error.rb +0 -1
  59. data/lib/graphql/backtrace/tracer.rb +39 -9
  60. data/lib/graphql/backtrace.rb +26 -18
  61. data/lib/graphql/dataloader/null_dataloader.rb +24 -0
  62. data/lib/graphql/dataloader/request.rb +19 -0
  63. data/lib/graphql/dataloader/request_all.rb +19 -0
  64. data/lib/graphql/dataloader/source.rb +164 -0
  65. data/lib/graphql/dataloader.rb +311 -0
  66. data/lib/graphql/date_encoding_error.rb +16 -0
  67. data/lib/graphql/deprecation.rb +9 -0
  68. data/lib/graphql/dig.rb +1 -1
  69. data/lib/graphql/execution/errors.rb +77 -44
  70. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  71. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  72. data/lib/graphql/execution/interpreter/arguments_cache.rb +104 -0
  73. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  74. data/lib/graphql/execution/interpreter/resolve.rb +62 -24
  75. data/lib/graphql/execution/interpreter/runtime.rb +826 -464
  76. data/lib/graphql/execution/interpreter.rb +206 -68
  77. data/lib/graphql/execution/lazy.rb +11 -21
  78. data/lib/graphql/execution/lookahead.rb +55 -136
  79. data/lib/graphql/execution/multiplex.rb +6 -162
  80. data/lib/graphql/execution.rb +11 -4
  81. data/lib/graphql/filter.rb +7 -2
  82. data/lib/graphql/integer_decoding_error.rb +17 -0
  83. data/lib/graphql/integer_encoding_error.rb +18 -2
  84. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  85. data/lib/graphql/introspection/directive_type.rb +11 -5
  86. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  87. data/lib/graphql/introspection/entry_points.rb +4 -17
  88. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  89. data/lib/graphql/introspection/field_type.rb +9 -5
  90. data/lib/graphql/introspection/input_value_type.rb +15 -3
  91. data/lib/graphql/introspection/introspection_query.rb +6 -92
  92. data/lib/graphql/introspection/schema_type.rb +11 -6
  93. data/lib/graphql/introspection/type_type.rb +31 -14
  94. data/lib/graphql/introspection.rb +100 -0
  95. data/lib/graphql/invalid_null_error.rb +18 -0
  96. data/lib/graphql/language/block_string.rb +20 -5
  97. data/lib/graphql/language/cache.rb +37 -0
  98. data/lib/graphql/language/document_from_schema_definition.rb +96 -44
  99. data/lib/graphql/language/lexer.rb +216 -1462
  100. data/lib/graphql/language/nodes.rb +126 -129
  101. data/lib/graphql/language/parser.rb +997 -933
  102. data/lib/graphql/language/parser.y +148 -118
  103. data/lib/graphql/language/printer.rb +48 -23
  104. data/lib/graphql/language/sanitized_printer.rb +222 -0
  105. data/lib/graphql/language/token.rb +0 -4
  106. data/lib/graphql/language/visitor.rb +192 -84
  107. data/lib/graphql/language.rb +2 -0
  108. data/lib/graphql/name_validator.rb +2 -7
  109. data/lib/graphql/pagination/active_record_relation_connection.rb +45 -3
  110. data/lib/graphql/pagination/array_connection.rb +6 -4
  111. data/lib/graphql/pagination/connection.rb +105 -23
  112. data/lib/graphql/pagination/connections.rb +62 -35
  113. data/lib/graphql/pagination/relation_connection.rb +88 -36
  114. data/lib/graphql/parse_error.rb +0 -1
  115. data/lib/graphql/query/context.rb +203 -198
  116. data/lib/graphql/query/fingerprint.rb +26 -0
  117. data/lib/graphql/query/input_validation_result.rb +33 -7
  118. data/lib/graphql/query/null_context.rb +22 -9
  119. data/lib/graphql/query/validation_pipeline.rb +16 -38
  120. data/lib/graphql/query/variable_validation_error.rb +3 -3
  121. data/lib/graphql/query/variables.rb +36 -12
  122. data/lib/graphql/query.rb +92 -44
  123. data/lib/graphql/railtie.rb +6 -102
  124. data/lib/graphql/rake_task/validate.rb +1 -1
  125. data/lib/graphql/rake_task.rb +41 -10
  126. data/lib/graphql/relay/range_add.rb +17 -10
  127. data/lib/graphql/relay.rb +0 -15
  128. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  129. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  130. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  131. data/lib/graphql/rubocop.rb +4 -0
  132. data/lib/graphql/schema/addition.rb +245 -0
  133. data/lib/graphql/schema/argument.rb +250 -46
  134. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  135. data/lib/graphql/schema/build_from_definition/resolve_map.rb +3 -1
  136. data/lib/graphql/schema/build_from_definition.rb +243 -89
  137. data/lib/graphql/schema/directive/deprecated.rb +1 -1
  138. data/lib/graphql/schema/directive/feature.rb +1 -1
  139. data/lib/graphql/schema/directive/flagged.rb +57 -0
  140. data/lib/graphql/schema/directive/include.rb +1 -1
  141. data/lib/graphql/schema/directive/one_of.rb +12 -0
  142. data/lib/graphql/schema/directive/skip.rb +1 -1
  143. data/lib/graphql/schema/directive/transform.rb +14 -2
  144. data/lib/graphql/schema/directive.rb +108 -20
  145. data/lib/graphql/schema/enum.rb +105 -44
  146. data/lib/graphql/schema/enum_value.rb +15 -25
  147. data/lib/graphql/schema/field/connection_extension.rb +50 -30
  148. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  149. data/lib/graphql/schema/field.rb +476 -331
  150. data/lib/graphql/schema/field_extension.rb +86 -2
  151. data/lib/graphql/schema/find_inherited_value.rb +6 -8
  152. data/lib/graphql/schema/finder.rb +5 -5
  153. data/lib/graphql/schema/input_object.rb +133 -121
  154. data/lib/graphql/schema/interface.rb +17 -45
  155. data/lib/graphql/schema/introspection_system.rb +3 -8
  156. data/lib/graphql/schema/late_bound_type.rb +8 -2
  157. data/lib/graphql/schema/list.rb +25 -8
  158. data/lib/graphql/schema/loader.rb +139 -103
  159. data/lib/graphql/schema/member/base_dsl_methods.rb +29 -35
  160. data/lib/graphql/schema/member/build_type.rb +19 -14
  161. data/lib/graphql/schema/member/has_arguments.rb +310 -26
  162. data/lib/graphql/schema/member/has_ast_node.rb +16 -1
  163. data/lib/graphql/schema/member/has_deprecation_reason.rb +24 -0
  164. data/lib/graphql/schema/member/has_directives.rb +118 -0
  165. data/lib/graphql/schema/member/has_fields.rb +164 -42
  166. data/lib/graphql/schema/member/has_interfaces.rb +129 -0
  167. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  168. data/lib/graphql/schema/member/has_validators.rb +57 -0
  169. data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
  170. data/lib/graphql/schema/member/type_system_helpers.rb +20 -3
  171. data/lib/graphql/schema/member/validates_input.rb +3 -3
  172. data/lib/graphql/schema/member.rb +6 -6
  173. data/lib/graphql/schema/mutation.rb +4 -9
  174. data/lib/graphql/schema/non_null.rb +12 -7
  175. data/lib/graphql/schema/object.rb +35 -69
  176. data/lib/graphql/schema/printer.rb +16 -34
  177. data/lib/graphql/schema/relay_classic_mutation.rb +90 -43
  178. data/lib/graphql/schema/resolver/has_payload_type.rb +51 -11
  179. data/lib/graphql/schema/resolver.rb +144 -79
  180. data/lib/graphql/schema/scalar.rb +27 -18
  181. data/lib/graphql/schema/subscription.rb +55 -26
  182. data/lib/graphql/schema/timeout.rb +45 -35
  183. data/lib/graphql/schema/type_expression.rb +1 -1
  184. data/lib/graphql/schema/type_membership.rb +21 -4
  185. data/lib/graphql/schema/union.rb +48 -13
  186. data/lib/graphql/schema/unique_within_type.rb +1 -2
  187. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  188. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  189. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  190. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  191. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  192. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  193. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  194. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  195. data/lib/graphql/schema/validator.rb +171 -0
  196. data/lib/graphql/schema/warden.rb +185 -32
  197. data/lib/graphql/schema/wrapper.rb +0 -5
  198. data/lib/graphql/schema.rb +471 -1116
  199. data/lib/graphql/static_validation/all_rules.rb +3 -0
  200. data/lib/graphql/static_validation/base_visitor.rb +13 -27
  201. data/lib/graphql/static_validation/definition_dependencies.rb +7 -2
  202. data/lib/graphql/static_validation/error.rb +3 -1
  203. data/lib/graphql/static_validation/literal_validator.rb +69 -26
  204. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +44 -87
  205. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +22 -6
  206. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +28 -22
  207. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  208. data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -6
  209. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +13 -13
  210. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
  211. data/lib/graphql/static_validation/rules/fields_will_merge.rb +92 -49
  212. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  213. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  214. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  215. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  216. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  217. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  218. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  219. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  220. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
  221. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +6 -7
  222. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
  223. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +9 -10
  224. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +14 -8
  225. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +4 -2
  226. data/lib/graphql/static_validation/validation_context.rb +13 -3
  227. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  228. data/lib/graphql/static_validation/validator.rb +32 -20
  229. data/lib/graphql/static_validation.rb +1 -2
  230. data/lib/graphql/string_encoding_error.rb +13 -3
  231. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +126 -19
  232. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  233. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
  234. data/lib/graphql/subscriptions/event.rb +81 -35
  235. data/lib/graphql/subscriptions/instrumentation.rb +0 -52
  236. data/lib/graphql/subscriptions/serialize.rb +53 -6
  237. data/lib/graphql/subscriptions.rb +113 -58
  238. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  239. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -21
  240. data/lib/graphql/tracing/appoptics_trace.rb +231 -0
  241. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  242. data/lib/graphql/tracing/appsignal_trace.rb +77 -0
  243. data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
  244. data/lib/graphql/tracing/data_dog_trace.rb +148 -0
  245. data/lib/graphql/tracing/data_dog_tracing.rb +26 -2
  246. data/lib/graphql/tracing/legacy_trace.rb +65 -0
  247. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  248. data/lib/graphql/tracing/new_relic_tracing.rb +1 -12
  249. data/lib/graphql/tracing/notifications_trace.rb +42 -0
  250. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  251. data/lib/graphql/tracing/platform_trace.rb +109 -0
  252. data/lib/graphql/tracing/platform_tracing.rb +64 -43
  253. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  254. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +5 -2
  255. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  256. data/lib/graphql/tracing/scout_trace.rb +72 -0
  257. data/lib/graphql/tracing/scout_tracing.rb +11 -0
  258. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  259. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  260. data/lib/graphql/tracing/trace.rb +75 -0
  261. data/lib/graphql/tracing.rb +23 -71
  262. data/lib/graphql/type_kinds.rb +6 -3
  263. data/lib/graphql/types/big_int.rb +5 -1
  264. data/lib/graphql/types/int.rb +10 -3
  265. data/lib/graphql/types/iso_8601_date.rb +20 -9
  266. data/lib/graphql/types/iso_8601_date_time.rb +36 -10
  267. data/lib/graphql/types/relay/base_connection.rb +18 -92
  268. data/lib/graphql/types/relay/base_edge.rb +2 -34
  269. data/lib/graphql/types/relay/connection_behaviors.rb +176 -0
  270. data/lib/graphql/types/relay/edge_behaviors.rb +75 -0
  271. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  272. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  273. data/lib/graphql/types/relay/node.rb +2 -4
  274. data/lib/graphql/types/relay/node_behaviors.rb +25 -0
  275. data/lib/graphql/types/relay/page_info.rb +2 -14
  276. data/lib/graphql/types/relay/page_info_behaviors.rb +30 -0
  277. data/lib/graphql/types/relay.rb +10 -5
  278. data/lib/graphql/types/string.rb +8 -2
  279. data/lib/graphql/unauthorized_error.rb +2 -2
  280. data/lib/graphql/version.rb +1 -1
  281. data/lib/graphql.rb +54 -65
  282. data/readme.md +3 -6
  283. metadata +116 -236
  284. data/lib/graphql/analysis/analyze_query.rb +0 -91
  285. data/lib/graphql/analysis/field_usage.rb +0 -45
  286. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  287. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  288. data/lib/graphql/analysis/query_complexity.rb +0 -88
  289. data/lib/graphql/analysis/query_depth.rb +0 -43
  290. data/lib/graphql/analysis/reducer_state.rb +0 -48
  291. data/lib/graphql/argument.rb +0 -131
  292. data/lib/graphql/authorization.rb +0 -82
  293. data/lib/graphql/backwards_compatibility.rb +0 -60
  294. data/lib/graphql/base_type.rb +0 -230
  295. data/lib/graphql/boolean_type.rb +0 -2
  296. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  297. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  298. data/lib/graphql/compatibility/execution_specification.rb +0 -435
  299. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  300. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -213
  301. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  302. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  303. data/lib/graphql/compatibility/query_parser_specification.rb +0 -264
  304. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -680
  305. data/lib/graphql/compatibility.rb +0 -5
  306. data/lib/graphql/define/assign_argument.rb +0 -12
  307. data/lib/graphql/define/assign_connection.rb +0 -13
  308. data/lib/graphql/define/assign_enum_value.rb +0 -18
  309. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  310. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  311. data/lib/graphql/define/assign_object_field.rb +0 -42
  312. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  313. data/lib/graphql/define/instance_definable.rb +0 -210
  314. data/lib/graphql/define/no_definition_error.rb +0 -7
  315. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  316. data/lib/graphql/define/type_definer.rb +0 -31
  317. data/lib/graphql/define.rb +0 -31
  318. data/lib/graphql/deprecated_dsl.rb +0 -42
  319. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  320. data/lib/graphql/directive/include_directive.rb +0 -2
  321. data/lib/graphql/directive/skip_directive.rb +0 -2
  322. data/lib/graphql/directive.rb +0 -107
  323. data/lib/graphql/enum_type.rb +0 -127
  324. data/lib/graphql/execution/execute.rb +0 -326
  325. data/lib/graphql/execution/flatten.rb +0 -40
  326. data/lib/graphql/execution/instrumentation.rb +0 -92
  327. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  328. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  329. data/lib/graphql/execution/typecast.rb +0 -50
  330. data/lib/graphql/field/resolve.rb +0 -59
  331. data/lib/graphql/field.rb +0 -222
  332. data/lib/graphql/float_type.rb +0 -2
  333. data/lib/graphql/function.rb +0 -124
  334. data/lib/graphql/id_type.rb +0 -2
  335. data/lib/graphql/input_object_type.rb +0 -132
  336. data/lib/graphql/int_type.rb +0 -2
  337. data/lib/graphql/interface_type.rb +0 -65
  338. data/lib/graphql/internal_representation/document.rb +0 -27
  339. data/lib/graphql/internal_representation/node.rb +0 -206
  340. data/lib/graphql/internal_representation/print.rb +0 -51
  341. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  342. data/lib/graphql/internal_representation/scope.rb +0 -88
  343. data/lib/graphql/internal_representation/visit.rb +0 -36
  344. data/lib/graphql/internal_representation.rb +0 -7
  345. data/lib/graphql/language/lexer.rl +0 -258
  346. data/lib/graphql/list_type.rb +0 -80
  347. data/lib/graphql/literal_validation_error.rb +0 -6
  348. data/lib/graphql/non_null_type.rb +0 -71
  349. data/lib/graphql/object_type.rb +0 -121
  350. data/lib/graphql/query/arguments.rb +0 -188
  351. data/lib/graphql/query/arguments_cache.rb +0 -25
  352. data/lib/graphql/query/executor.rb +0 -53
  353. data/lib/graphql/query/literal_input.rb +0 -136
  354. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  355. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  356. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  357. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  358. data/lib/graphql/query/serial_execution.rb +0 -39
  359. data/lib/graphql/relay/array_connection.rb +0 -85
  360. data/lib/graphql/relay/base_connection.rb +0 -176
  361. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  362. data/lib/graphql/relay/connection_resolve.rb +0 -43
  363. data/lib/graphql/relay/connection_type.rb +0 -41
  364. data/lib/graphql/relay/edge.rb +0 -27
  365. data/lib/graphql/relay/edge_type.rb +0 -19
  366. data/lib/graphql/relay/edges_instrumentation.rb +0 -40
  367. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  368. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  369. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  370. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  371. data/lib/graphql/relay/mutation/result.rb +0 -38
  372. data/lib/graphql/relay/mutation.rb +0 -105
  373. data/lib/graphql/relay/node.rb +0 -36
  374. data/lib/graphql/relay/page_info.rb +0 -7
  375. data/lib/graphql/relay/relation_connection.rb +0 -190
  376. data/lib/graphql/relay/type_extensions.rb +0 -30
  377. data/lib/graphql/scalar_type.rb +0 -76
  378. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  379. data/lib/graphql/schema/default_parse_error.rb +0 -10
  380. data/lib/graphql/schema/default_type_error.rb +0 -15
  381. data/lib/graphql/schema/member/accepts_definition.rb +0 -152
  382. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -31
  383. data/lib/graphql/schema/member/instrumentation.rb +0 -132
  384. data/lib/graphql/schema/middleware_chain.rb +0 -82
  385. data/lib/graphql/schema/possible_types.rb +0 -39
  386. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  387. data/lib/graphql/schema/timeout_middleware.rb +0 -86
  388. data/lib/graphql/schema/traversal.rb +0 -228
  389. data/lib/graphql/schema/validation.rb +0 -303
  390. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  391. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  392. data/lib/graphql/string_type.rb +0 -2
  393. data/lib/graphql/subscriptions/subscription_root.rb +0 -65
  394. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  395. data/lib/graphql/types/relay/base_field.rb +0 -22
  396. data/lib/graphql/types/relay/base_interface.rb +0 -29
  397. data/lib/graphql/types/relay/base_object.rb +0 -26
  398. data/lib/graphql/types/relay/node_field.rb +0 -43
  399. data/lib/graphql/types/relay/nodes_field.rb +0 -45
  400. data/lib/graphql/union_type.rb +0 -113
  401. data/lib/graphql/upgrader/member.rb +0 -936
  402. data/lib/graphql/upgrader/schema.rb +0 -37
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
  require "graphql/language/block_string"
3
3
  require "graphql/language/printer"
4
+ require "graphql/language/sanitized_printer"
4
5
  require "graphql/language/document_from_schema_definition"
5
6
  require "graphql/language/generation"
6
7
  require "graphql/language/lexer"
7
8
  require "graphql/language/nodes"
9
+ require "graphql/language/cache"
8
10
  require "graphql/language/parser"
9
11
  require "graphql/language/token"
10
12
  require "graphql/language/visitor"
@@ -4,13 +4,8 @@ module GraphQL
4
4
  VALID_NAME_REGEX = /^[_a-zA-Z][_a-zA-Z0-9]*$/
5
5
 
6
6
  def self.validate!(name)
7
- raise GraphQL::InvalidNameError.new(name, VALID_NAME_REGEX) unless valid?(name)
8
- end
9
-
10
- private
11
-
12
- def self.valid?(name)
13
- name =~ VALID_NAME_REGEX
7
+ name = name.is_a?(String) ? name : name.to_s
8
+ raise GraphQL::InvalidNameError.new(name, VALID_NAME_REGEX) unless name.match?(VALID_NAME_REGEX)
14
9
  end
15
10
  end
16
11
  end
@@ -5,21 +5,39 @@ module GraphQL
5
5
  module Pagination
6
6
  # Customizes `RelationConnection` to work with `ActiveRecord::Relation`s.
7
7
  class ActiveRecordRelationConnection < Pagination::RelationConnection
8
+ private
9
+
8
10
  def relation_count(relation)
9
- if relation.respond_to?(:unscope)
11
+ int_or_hash = if already_loaded?(relation)
12
+ relation.size
13
+ elsif relation.respond_to?(:unscope)
10
14
  relation.unscope(:order).count(:all)
11
15
  else
12
16
  # Rails 3
13
17
  relation.count
14
18
  end
19
+ if int_or_hash.is_a?(Integer)
20
+ int_or_hash
21
+ else
22
+ # Grouped relations return count-by-group hashes
23
+ int_or_hash.length
24
+ end
15
25
  end
16
26
 
17
27
  def relation_limit(relation)
18
- relation.limit_value
28
+ if relation.is_a?(Array)
29
+ nil
30
+ else
31
+ relation.limit_value
32
+ end
19
33
  end
20
34
 
21
35
  def relation_offset(relation)
22
- relation.offset_value
36
+ if relation.is_a?(Array)
37
+ nil
38
+ else
39
+ relation.offset_value
40
+ end
23
41
  end
24
42
 
25
43
  def null_relation(relation)
@@ -30,6 +48,30 @@ module GraphQL
30
48
  relation.where("1=2")
31
49
  end
32
50
  end
51
+
52
+ def set_limit(nodes, limit)
53
+ if already_loaded?(nodes)
54
+ nodes.take(limit)
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ def set_offset(nodes, offset)
61
+ if already_loaded?(nodes)
62
+ # If the client sent a bogus cursor beyond the size of the relation,
63
+ # it might get `nil` from `#[...]`, so return an empty array in that case
64
+ nodes[offset..-1] || []
65
+ else
66
+ super
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def already_loaded?(relation)
73
+ relation.is_a?(Array) || relation.loaded?
74
+ end
33
75
  end
34
76
  end
35
77
  end
@@ -21,7 +21,7 @@ module GraphQL
21
21
 
22
22
  def cursor_for(item)
23
23
  idx = items.find_index(item) + 1
24
- context.schema.cursor_encoder.encode(idx.to_s)
24
+ encode(idx.to_s)
25
25
  end
26
26
 
27
27
  private
@@ -35,9 +35,11 @@ module GraphQL
35
35
  def load_nodes
36
36
  @nodes ||= begin
37
37
  sliced_nodes = if before && after
38
- items[index_from_cursor(after)..index_from_cursor(before)-1] || []
38
+ end_idx = index_from_cursor(before)-1
39
+ end_idx < 0 ? [] : items[index_from_cursor(after)..end_idx] || []
39
40
  elsif before
40
- items[0..index_from_cursor(before)-2] || []
41
+ end_idx = index_from_cursor(before)-2
42
+ end_idx < 0 ? [] : items[0..end_idx] || []
41
43
  elsif after
42
44
  items[index_from_cursor(after)..-1] || []
43
45
  else
@@ -59,7 +61,7 @@ module GraphQL
59
61
  sliced_nodes.count > first
60
62
  elsif before
61
63
  # The original array is longer than the `before` index
62
- index_from_cursor(before) < items.length
64
+ index_from_cursor(before) < items.length + 1
63
65
  else
64
66
  false
65
67
  end
@@ -15,67 +15,137 @@ module GraphQL
15
15
  class PaginationImplementationMissingError < GraphQL::Error
16
16
  end
17
17
 
18
- # @return [Class] The class to use for wrapping items as `edges { ... }`. Defaults to `Connection::Edge`
19
- def self.edge_class
20
- self::Edge
21
- end
22
-
23
18
  # @return [Object] A list object, from the application. This is the unpaginated value passed into the connection.
24
19
  attr_reader :items
25
20
 
26
21
  # @return [GraphQL::Query::Context]
27
22
  attr_accessor :context
28
23
 
24
+ # @return [Object] the object this collection belongs to
25
+ attr_accessor :parent
26
+
29
27
  # Raw access to client-provided values. (`max_page_size` not applied to first or last.)
30
28
  attr_accessor :before_value, :after_value, :first_value, :last_value
31
29
 
32
- # @return [String, nil] the client-provided cursor
30
+ # @return [String, nil] the client-provided cursor. `""` is treated as `nil`.
33
31
  def before
34
- @before_value
32
+ if defined?(@before)
33
+ @before
34
+ else
35
+ @before = @before_value == "" ? nil : @before_value
36
+ end
35
37
  end
36
38
 
37
- # @return [String, nil] the client-provided cursor
39
+ # @return [String, nil] the client-provided cursor. `""` is treated as `nil`.
38
40
  def after
39
- @after_value
41
+ if defined?(@after)
42
+ @after
43
+ else
44
+ @after = @after_value == "" ? nil : @after_value
45
+ end
40
46
  end
41
47
 
48
+ # @return [Hash<Symbol => Object>] The field arguments from the field that returned this connection
49
+ attr_accessor :arguments
50
+
42
51
  # @param items [Object] some unpaginated collection item, like an `Array` or `ActiveRecord::Relation`
43
52
  # @param context [Query::Context]
53
+ # @param parent [Object] The object this collection belongs to
44
54
  # @param first [Integer, nil] The limit parameter from the client, if it provided one
45
55
  # @param after [String, nil] A cursor for pagination, if the client provided one
46
56
  # @param last [Integer, nil] Limit parameter from the client, if provided
47
57
  # @param before [String, nil] A cursor for pagination, if the client provided one.
48
- # @param max_page_size [Integer, nil] A configured value to cap the result size. Applied as `first` if neither first or last are given.
49
- def initialize(items, context: nil, first: nil, after: nil, max_page_size: nil, last: nil, before: nil)
58
+ # @param arguments [Hash] The arguments to the field that returned the collection wrapped by this connection
59
+ # @param max_page_size [Integer, nil] A configured value to cap the result size. Applied as `first` if neither first or last are given and no `default_page_size` is set.
60
+ # @param default_page_size [Integer, nil] A configured value to determine the result size when neither first or last are given.
61
+ def initialize(items, parent: nil, field: nil, context: nil, first: nil, after: nil, max_page_size: NOT_CONFIGURED, default_page_size: NOT_CONFIGURED, last: nil, before: nil, edge_class: nil, arguments: nil)
50
62
  @items = items
63
+ @parent = parent
51
64
  @context = context
65
+ @field = field
52
66
  @first_value = first
53
67
  @after_value = after
54
68
  @last_value = last
55
69
  @before_value = before
56
- @max_page_size = max_page_size
70
+ @arguments = arguments
71
+ @edge_class = edge_class || self.class::Edge
72
+ # This is only true if the object was _initialized_ with an override
73
+ # or if one is assigned later.
74
+ @has_max_page_size_override = max_page_size != NOT_CONFIGURED
75
+ @max_page_size = if max_page_size == NOT_CONFIGURED
76
+ nil
77
+ else
78
+ max_page_size
79
+ end
80
+ @has_default_page_size_override = default_page_size != NOT_CONFIGURED
81
+ @default_page_size = if default_page_size == NOT_CONFIGURED
82
+ nil
83
+ else
84
+ default_page_size
85
+ end
86
+ end
87
+
88
+ def max_page_size=(new_value)
89
+ @has_max_page_size_override = true
90
+ @max_page_size = new_value
57
91
  end
58
92
 
59
- attr_writer :max_page_size
60
93
  def max_page_size
61
- @max_page_size ||= context.schema.default_max_page_size
94
+ if @has_max_page_size_override
95
+ @max_page_size
96
+ else
97
+ context.schema.default_max_page_size
98
+ end
99
+ end
100
+
101
+ def has_max_page_size_override?
102
+ @has_max_page_size_override
103
+ end
104
+
105
+ def default_page_size=(new_value)
106
+ @has_default_page_size_override = true
107
+ @default_page_size = new_value
108
+ end
109
+
110
+ def default_page_size
111
+ if @has_default_page_size_override
112
+ @default_page_size
113
+ else
114
+ context.schema.default_page_size
115
+ end
116
+ end
117
+
118
+ def has_default_page_size_override?
119
+ @has_default_page_size_override
62
120
  end
63
121
 
64
122
  attr_writer :first
65
123
  # @return [Integer, nil]
66
124
  # A clamped `first` value.
67
125
  # (The underlying instance variable doesn't have limits on it.)
68
- # If neither `first` nor `last` is given, but `max_page_size` is present, max_page_size is used for first.
126
+ # If neither `first` nor `last` is given, but `default_page_size` is
127
+ # present, default_page_size is used for first. If `default_page_size`
128
+ # is greater than `max_page_size``, it'll be clamped down to
129
+ # `max_page_size`. If `default_page_size` is nil, use `max_page_size`.
69
130
  def first
70
131
  @first ||= begin
71
132
  capped = limit_pagination_argument(@first_value, max_page_size)
72
133
  if capped.nil? && last.nil?
73
- capped = max_page_size
134
+ capped = limit_pagination_argument(default_page_size, max_page_size) || max_page_size
74
135
  end
75
136
  capped
76
137
  end
77
138
  end
78
139
 
140
+ # This is called by `Relay::RangeAdd` -- it can be overridden
141
+ # when `item` needs some modifications based on this connection's state.
142
+ #
143
+ # @param item [Object] An item newly added to `items`
144
+ # @return [Edge]
145
+ def range_add_edge(item)
146
+ edge_class.new(item, self)
147
+ end
148
+
79
149
  attr_writer :last
80
150
  # @return [Integer, nil] A clamped `last` value. (The underlying instance variable doesn't have limits on it)
81
151
  def last
@@ -84,9 +154,15 @@ module GraphQL
84
154
 
85
155
  # @return [Array<Edge>] {nodes}, but wrapped with Edge instances
86
156
  def edges
87
- @edges ||= nodes.map { |n| self.class.edge_class.new(n, self) }
157
+ @edges ||= nodes.map { |n| @edge_class.new(n, self) }
88
158
  end
89
159
 
160
+ # @return [Class] A wrapper class for edges of this connection
161
+ attr_accessor :edge_class
162
+
163
+ # @return [GraphQL::Schema::Field] The field this connection was returned by
164
+ attr_accessor :field
165
+
90
166
  # @return [Array<Object>] A slice of {items}, constrained by {@first_value}/{@after_value}/{@last_value}/{@before_value}
91
167
  def nodes
92
168
  raise PaginationImplementationMissingError, "Implement #{self.class}#nodes to paginate `@items`"
@@ -147,23 +223,29 @@ module GraphQL
147
223
  end
148
224
 
149
225
  def decode(cursor)
150
- context.schema.cursor_encoder.decode(cursor)
226
+ context.schema.cursor_encoder.decode(cursor, nonce: true)
227
+ end
228
+
229
+ def encode(cursor)
230
+ context.schema.cursor_encoder.encode(cursor, nonce: true)
151
231
  end
152
232
 
153
233
  # A wrapper around paginated items. It includes a {cursor} for pagination
154
234
  # and could be extended with custom relationship-level data.
155
235
  class Edge
156
- def initialize(item, connection)
236
+ attr_reader :node
237
+
238
+ def initialize(node, connection)
157
239
  @connection = connection
158
- @item = item
240
+ @node = node
159
241
  end
160
242
 
161
- def node
162
- @item
243
+ def parent
244
+ @connection.parent
163
245
  end
164
246
 
165
247
  def cursor
166
- @connection.cursor_for(@item)
248
+ @cursor ||= @connection.cursor_for(@node)
167
249
  end
168
250
  end
169
251
  end
@@ -6,20 +6,13 @@ module GraphQL
6
6
  #
7
7
  # Attach as a plugin.
8
8
  #
9
- # @example Using new default connections
10
- # class MySchema < GraphQL::Schema
11
- # use GraphQL::Pagination::Connections
12
- # end
13
- #
14
9
  # @example Adding a custom wrapper
15
10
  # class MySchema < GraphQL::Schema
16
- # use GraphQL::Pagination::Connections
17
11
  # connections.add(MyApp::SearchResults, MyApp::SearchResultsConnection)
18
12
  # end
19
13
  #
20
14
  # @example Removing default connection support for arrays (they can still be manually wrapped)
21
15
  # class MySchema < GraphQL::Schema
22
- # use GraphQL::Pagination::Connections
23
16
  # connections.delete(Array)
24
17
  # end
25
18
  #
@@ -28,18 +21,8 @@ module GraphQL
28
21
  class ImplementationMissingError < GraphQL::Error
29
22
  end
30
23
 
31
- def self.use(schema_defn)
32
- if schema_defn.is_a?(Class)
33
- schema_defn.connections = self.new
34
- else
35
- # Unwrap a `.define` object
36
- schema_defn = schema_defn.target
37
- schema_defn.connections = self.new
38
- schema_defn.class.connections = schema_defn.connections
39
- end
40
- end
41
-
42
- def initialize
24
+ def initialize(schema:)
25
+ @schema = schema
43
26
  @wrappers = {}
44
27
  add_default
45
28
  end
@@ -52,29 +35,68 @@ module GraphQL
52
35
  @wrappers.delete(nodes_class)
53
36
  end
54
37
 
55
- # Used by the runtime to wrap values in connection wrappers.
56
- # @api Private
57
- def wrap(field, object, arguments, context)
38
+ def all_wrappers
39
+ all_wrappers = {}
40
+ @schema.ancestors.reverse_each do |schema_class|
41
+ if schema_class.respond_to?(:connections) && (c = schema_class.connections)
42
+ all_wrappers.merge!(c.wrappers)
43
+ end
44
+ end
45
+ all_wrappers
46
+ end
47
+
48
+ def wrapper_for(items, wrappers: all_wrappers)
58
49
  impl = nil
59
- object.class.ancestors.each { |cls|
60
- impl = @wrappers[cls]
50
+
51
+ items.class.ancestors.each { |cls|
52
+ impl = wrappers[cls]
61
53
  break if impl
62
54
  }
63
55
 
64
- if impl.nil?
65
- raise ImplementationMissingError, "Couldn't find a connection wrapper for #{object.class} during #{field.path} (#{object.inspect})"
56
+ impl
57
+ end
58
+
59
+ # Used by the runtime to wrap values in connection wrappers.
60
+ # @api Private
61
+ def wrap(field, parent, items, arguments, context)
62
+ return items if GraphQL::Execution::Interpreter::RawValue === items
63
+ wrappers = context ? context.namespace(:connections)[:all_wrappers] : all_wrappers
64
+ impl = wrapper_for(items, wrappers: wrappers)
65
+
66
+ if impl
67
+ impl.new(
68
+ items,
69
+ context: context,
70
+ parent: parent,
71
+ field: field,
72
+ max_page_size: field.has_max_page_size? ? field.max_page_size : context.schema.default_max_page_size,
73
+ default_page_size: field.has_default_page_size? ? field.default_page_size : context.schema.default_page_size,
74
+ first: arguments[:first],
75
+ after: arguments[:after],
76
+ last: arguments[:last],
77
+ before: arguments[:before],
78
+ arguments: arguments,
79
+ edge_class: edge_class_for_field(field),
80
+ )
81
+ else
82
+ raise ImplementationMissingError, "Couldn't find a connection wrapper for #{items.class} during #{field.path} (#{items.inspect})"
66
83
  end
84
+ end
67
85
 
68
- impl.new(
69
- object,
70
- context: context,
71
- max_page_size: field.max_page_size || context.schema.default_max_page_size,
72
- first: arguments[:first],
73
- after: arguments[:after],
74
- last: arguments[:last],
75
- before: arguments[:before],
76
- )
86
+ # use an override if there is one
87
+ # @api private
88
+ def edge_class_for_field(field)
89
+ conn_type = field.type.unwrap
90
+ conn_type_edge_type = conn_type.respond_to?(:edge_class) && conn_type.edge_class
91
+ if conn_type_edge_type && conn_type_edge_type != Pagination::Connection::Edge
92
+ conn_type_edge_type
93
+ else
94
+ nil
95
+ end
77
96
  end
97
+ protected
98
+
99
+ attr_reader :wrappers
78
100
 
79
101
  private
80
102
 
@@ -102,6 +124,11 @@ module GraphQL
102
124
  if defined?(Mongoid::Association::Referenced::HasMany::Targets::Enumerable)
103
125
  add(Mongoid::Association::Referenced::HasMany::Targets::Enumerable, Pagination::MongoidRelationConnection)
104
126
  end
127
+
128
+ # Mongoid 7.3+
129
+ if defined?(Mongoid::Association::Referenced::HasMany::Enumerable)
130
+ add(Mongoid::Association::Referenced::HasMany::Enumerable, Pagination::MongoidRelationConnection)
131
+ end
105
132
  end
106
133
  end
107
134
  end
@@ -12,7 +12,7 @@ module GraphQL
12
12
 
13
13
  def has_previous_page
14
14
  if @has_previous_page.nil?
15
- @has_previous_page = if @after_offset && @after_offset > 0
15
+ @has_previous_page = if after_offset && after_offset > 0
16
16
  true
17
17
  elsif last
18
18
  # See whether there are any nodes _before_ the current offset.
@@ -29,10 +29,14 @@ module GraphQL
29
29
 
30
30
  def has_next_page
31
31
  if @has_next_page.nil?
32
- @has_next_page = if @before_offset && @before_offset > 0
32
+ @has_next_page = if before_offset && before_offset > 0
33
33
  true
34
34
  elsif first
35
- relation_count(set_limit(sliced_nodes, first + 1)) == first + 1
35
+ if @nodes && @nodes.count < first
36
+ false
37
+ else
38
+ relation_larger_than(sliced_nodes, @sliced_nodes_offset, first)
39
+ end
36
40
  else
37
41
  false
38
42
  end
@@ -43,12 +47,20 @@ module GraphQL
43
47
  def cursor_for(item)
44
48
  load_nodes
45
49
  # index in nodes + existing offset + 1 (because it's offset, not index)
46
- offset = nodes.index(item) + 1 + (@paged_nodes_offset || 0) + (relation_offset(items) || 0)
47
- context.schema.cursor_encoder.encode(offset.to_s)
50
+ offset = nodes.index(item) + 1 + (@paged_nodes_offset || 0) - (relation_offset(items) || 0)
51
+ encode(offset.to_s)
48
52
  end
49
53
 
50
54
  private
51
55
 
56
+ # @param relation [Object] A database query object
57
+ # @param _initial_offset [Integer] The number of items already excluded from the relation
58
+ # @param size [Integer] The value against which we check the relation size
59
+ # @return [Boolean] True if the number of items in this relation is larger than `size`
60
+ def relation_larger_than(relation, _initial_offset, size)
61
+ relation_count(set_limit(relation, size + 1)) == size + 1
62
+ end
63
+
52
64
  # @param relation [Object] A database query object
53
65
  # @return [Integer, nil] The offset value, or nil if there isn't one
54
66
  def relation_offset(relation)
@@ -100,67 +112,107 @@ module GraphQL
100
112
  end
101
113
  end
102
114
 
103
- # Apply `before` and `after` to the underlying `items`,
104
- # returning a new relation.
105
- def sliced_nodes
106
- @sliced_nodes ||= begin
107
- paginated_nodes = items
108
- @after_offset = after && offset_from_cursor(after)
109
- @before_offset = before && offset_from_cursor(before)
115
+ def calculate_sliced_nodes_parameters
116
+ if defined?(@sliced_nodes_limit)
117
+ return
118
+ else
119
+ next_offset = relation_offset(items) || 0
120
+ relation_limit = relation_limit(items)
110
121
 
111
- if @after_offset
112
- previous_offset = relation_offset(items) || 0
113
- paginated_nodes = set_offset(paginated_nodes, previous_offset + @after_offset)
122
+ if after_offset
123
+ next_offset += after_offset
114
124
  end
115
125
 
116
- if @before_offset && @after_offset
117
- if @after_offset < @before_offset
126
+ if before_offset && after_offset
127
+ if after_offset < before_offset
118
128
  # Get the number of items between the two cursors
119
- space_between = @before_offset - @after_offset - 1
120
- paginated_nodes = set_limit(paginated_nodes, space_between)
129
+ space_between = before_offset - after_offset - 1
130
+ relation_limit = space_between
121
131
  else
122
- # TODO I think this is untested
123
132
  # The cursors overextend one another to an empty set
124
- paginated_nodes = null_relation(paginated_nodes)
133
+ @sliced_nodes_null_relation = true
125
134
  end
126
- elsif @before_offset
135
+ elsif before_offset
127
136
  # Use limit to cut off the tail of the relation
128
- paginated_nodes = set_limit(paginated_nodes, @before_offset - 1)
137
+ relation_limit = before_offset - 1
138
+ end
139
+
140
+ @sliced_nodes_limit = relation_limit
141
+ @sliced_nodes_offset = next_offset
142
+ end
143
+ end
144
+
145
+ # Apply `before` and `after` to the underlying `items`,
146
+ # returning a new relation.
147
+ def sliced_nodes
148
+ @sliced_nodes ||= begin
149
+ calculate_sliced_nodes_parameters
150
+ paginated_nodes = items
151
+
152
+ if @sliced_nodes_null_relation
153
+ paginated_nodes = null_relation(paginated_nodes)
154
+ else
155
+ if @sliced_nodes_limit
156
+ paginated_nodes = set_limit(paginated_nodes, @sliced_nodes_limit)
157
+ end
158
+
159
+ if @sliced_nodes_offset
160
+ paginated_nodes = set_offset(paginated_nodes, @sliced_nodes_offset)
161
+ end
129
162
  end
130
163
 
131
164
  paginated_nodes
132
165
  end
133
166
  end
134
167
 
168
+ # @return [Integer, nil]
169
+ def before_offset
170
+ @before_offset ||= before && offset_from_cursor(before)
171
+ end
172
+
173
+ # @return [Integer, nil]
174
+ def after_offset
175
+ @after_offset ||= after && offset_from_cursor(after)
176
+ end
177
+
135
178
  # Apply `first` and `last` to `sliced_nodes`,
136
179
  # returning a new relation
137
180
  def limited_nodes
138
181
  @limited_nodes ||= begin
139
- paginated_nodes = sliced_nodes
182
+ calculate_sliced_nodes_parameters
183
+ if @sliced_nodes_null_relation
184
+ # it's an empty set
185
+ return sliced_nodes
186
+ end
187
+ relation_limit = @sliced_nodes_limit
188
+ relation_offset = @sliced_nodes_offset
140
189
 
141
- if first && (relation_limit(paginated_nodes).nil? || relation_limit(paginated_nodes) > first) && last.nil?
190
+ if first && (relation_limit.nil? || relation_limit > first)
142
191
  # `first` would create a stricter limit that the one already applied, so add it
143
- paginated_nodes = set_limit(paginated_nodes, first)
192
+ relation_limit = first
144
193
  end
145
194
 
146
195
  if last
147
- if (lv = relation_limit(paginated_nodes))
148
- if last <= lv
196
+ if relation_limit
197
+ if last <= relation_limit
149
198
  # `last` is a smaller slice than the current limit, so apply it
150
- offset = (relation_offset(paginated_nodes) || 0) + (lv - last)
151
- paginated_nodes = set_offset(paginated_nodes, offset)
152
- paginated_nodes = set_limit(paginated_nodes, last)
199
+ relation_offset += (relation_limit - last)
200
+ relation_limit = last
153
201
  end
154
202
  else
155
203
  # No limit, so get the last items
156
- sliced_nodes_count = relation_count(@sliced_nodes)
157
- offset = (relation_offset(paginated_nodes) || 0) + sliced_nodes_count - [last, sliced_nodes_count].min
158
- paginated_nodes = set_offset(paginated_nodes, offset)
159
- paginated_nodes = set_limit(paginated_nodes, last)
204
+ sliced_nodes_count = relation_count(sliced_nodes)
205
+ relation_offset += (sliced_nodes_count - [last, sliced_nodes_count].min)
206
+ relation_limit = last
160
207
  end
161
208
  end
162
209
 
163
- @paged_nodes_offset = relation_offset(paginated_nodes)
210
+ @paged_nodes_offset = relation_offset
211
+ paginated_nodes = items
212
+ paginated_nodes = set_offset(paginated_nodes, relation_offset)
213
+ if relation_limit
214
+ paginated_nodes = set_limit(paginated_nodes, relation_limit)
215
+ end
164
216
  paginated_nodes
165
217
  end
166
218
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # test_via: language/parser.rb
3
2
  module GraphQL
4
3
  class ParseError < GraphQL::Error
5
4
  attr_reader :line, :col, :query