graphql 1.12.12 → 2.2.14

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 (392) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +3 -8
  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 +14 -4
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  12. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_generator.rb +5 -30
  14. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  15. data/lib/generators/graphql/object_generator.rb +10 -38
  16. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  17. data/lib/generators/graphql/relay.rb +23 -12
  18. data/lib/generators/graphql/scalar_generator.rb +4 -2
  19. data/lib/generators/graphql/templates/base_argument.erb +2 -0
  20. data/lib/generators/graphql/templates/base_connection.erb +2 -0
  21. data/lib/generators/graphql/templates/base_edge.erb +2 -0
  22. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  23. data/lib/generators/graphql/templates/base_field.erb +2 -0
  24. data/lib/generators/graphql/templates/base_input_object.erb +2 -0
  25. data/lib/generators/graphql/templates/base_interface.erb +2 -0
  26. data/lib/generators/graphql/templates/base_object.erb +2 -0
  27. data/lib/generators/graphql/templates/base_resolver.erb +6 -0
  28. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  29. data/lib/generators/graphql/templates/base_union.erb +2 -0
  30. data/lib/generators/graphql/templates/enum.erb +5 -1
  31. data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
  32. data/lib/generators/graphql/templates/input.erb +9 -0
  33. data/lib/generators/graphql/templates/interface.erb +4 -2
  34. data/lib/generators/graphql/templates/loader.erb +2 -0
  35. data/lib/generators/graphql/templates/mutation.erb +3 -1
  36. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  37. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  38. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  39. data/lib/generators/graphql/templates/node_type.erb +2 -0
  40. data/lib/generators/graphql/templates/object.erb +4 -2
  41. data/lib/generators/graphql/templates/query_type.erb +2 -0
  42. data/lib/generators/graphql/templates/scalar.erb +3 -1
  43. data/lib/generators/graphql/templates/schema.erb +19 -2
  44. data/lib/generators/graphql/templates/union.erb +4 -2
  45. data/lib/generators/graphql/type_generator.rb +46 -10
  46. data/lib/generators/graphql/union_generator.rb +5 -5
  47. data/lib/graphql/analysis/ast/analyzer.rb +7 -0
  48. data/lib/graphql/analysis/ast/field_usage.rb +55 -1
  49. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
  50. data/lib/graphql/analysis/ast/query_complexity.rb +88 -140
  51. data/lib/graphql/analysis/ast/query_depth.rb +7 -3
  52. data/lib/graphql/analysis/ast/visitor.rb +50 -42
  53. data/lib/graphql/analysis/ast.rb +26 -23
  54. data/lib/graphql/analysis.rb +0 -7
  55. data/lib/graphql/backtrace/table.rb +4 -22
  56. data/lib/graphql/backtrace/trace.rb +93 -0
  57. data/lib/graphql/backtrace/tracer.rb +8 -6
  58. data/lib/graphql/backtrace.rb +3 -8
  59. data/lib/graphql/coercion_error.rb +1 -9
  60. data/lib/graphql/dataloader/async_dataloader.rb +85 -0
  61. data/lib/graphql/dataloader/null_dataloader.rb +3 -1
  62. data/lib/graphql/dataloader/request.rb +5 -0
  63. data/lib/graphql/dataloader/source.rb +120 -31
  64. data/lib/graphql/dataloader.rb +168 -142
  65. data/lib/graphql/date_encoding_error.rb +16 -0
  66. data/lib/graphql/dig.rb +1 -1
  67. data/lib/graphql/duration_encoding_error.rb +16 -0
  68. data/lib/graphql/execution/errors.rb +12 -81
  69. data/lib/graphql/execution/interpreter/arguments.rb +2 -2
  70. data/lib/graphql/execution/interpreter/arguments_cache.rb +36 -34
  71. data/lib/graphql/execution/interpreter/resolve.rb +32 -2
  72. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +170 -0
  73. data/lib/graphql/execution/interpreter/runtime.rb +414 -341
  74. data/lib/graphql/execution/interpreter.rb +122 -80
  75. data/lib/graphql/execution/lazy.rb +11 -21
  76. data/lib/graphql/execution/lookahead.rb +125 -54
  77. data/lib/graphql/execution/multiplex.rb +4 -172
  78. data/lib/graphql/execution.rb +11 -4
  79. data/lib/graphql/integer_encoding_error.rb +18 -2
  80. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  81. data/lib/graphql/introspection/directive_type.rb +5 -3
  82. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  83. data/lib/graphql/introspection/entry_points.rb +11 -18
  84. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  85. data/lib/graphql/introspection/field_type.rb +3 -3
  86. data/lib/graphql/introspection/input_value_type.rb +10 -4
  87. data/lib/graphql/introspection/schema_type.rb +12 -5
  88. data/lib/graphql/introspection/type_type.rb +25 -12
  89. data/lib/graphql/introspection.rb +6 -2
  90. data/lib/graphql/language/block_string.rb +37 -25
  91. data/lib/graphql/language/definition_slice.rb +1 -1
  92. data/lib/graphql/language/document_from_schema_definition.rb +78 -65
  93. data/lib/graphql/language/lexer.rb +345 -1467
  94. data/lib/graphql/language/nodes.rb +145 -91
  95. data/lib/graphql/language/parser.rb +701 -1921
  96. data/lib/graphql/language/printer.rb +351 -155
  97. data/lib/graphql/language/sanitized_printer.rb +25 -27
  98. data/lib/graphql/language/static_visitor.rb +167 -0
  99. data/lib/graphql/language/token.rb +0 -4
  100. data/lib/graphql/language/visitor.rb +188 -141
  101. data/lib/graphql/language.rb +1 -0
  102. data/lib/graphql/load_application_object_failed_error.rb +5 -1
  103. data/lib/graphql/name_validator.rb +0 -4
  104. data/lib/graphql/pagination/active_record_relation_connection.rb +37 -8
  105. data/lib/graphql/pagination/array_connection.rb +8 -6
  106. data/lib/graphql/pagination/connection.rb +61 -7
  107. data/lib/graphql/pagination/connections.rb +22 -23
  108. data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
  109. data/lib/graphql/pagination/relation_connection.rb +60 -28
  110. data/lib/graphql/query/context/scoped_context.rb +101 -0
  111. data/lib/graphql/query/context.rb +109 -189
  112. data/lib/graphql/query/input_validation_result.rb +10 -1
  113. data/lib/graphql/query/null_context.rb +14 -29
  114. data/lib/graphql/query/validation_pipeline.rb +15 -39
  115. data/lib/graphql/query/variable_validation_error.rb +2 -2
  116. data/lib/graphql/query/variables.rb +35 -17
  117. data/lib/graphql/query.rb +78 -65
  118. data/lib/graphql/railtie.rb +8 -109
  119. data/lib/graphql/rake_task/validate.rb +1 -1
  120. data/lib/graphql/rake_task.rb +30 -11
  121. data/lib/graphql/relay/range_add.rb +9 -16
  122. data/lib/graphql/relay.rb +0 -15
  123. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  124. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  125. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  126. data/lib/graphql/rubocop.rb +4 -0
  127. data/lib/graphql/schema/addition.rb +78 -45
  128. data/lib/graphql/schema/always_visible.rb +10 -0
  129. data/lib/graphql/schema/argument.rb +134 -80
  130. data/lib/graphql/schema/base_64_encoder.rb +3 -5
  131. data/lib/graphql/schema/build_from_definition.rb +60 -38
  132. data/lib/graphql/schema/directive/feature.rb +1 -1
  133. data/lib/graphql/schema/directive/flagged.rb +2 -2
  134. data/lib/graphql/schema/directive/include.rb +1 -1
  135. data/lib/graphql/schema/directive/one_of.rb +24 -0
  136. data/lib/graphql/schema/directive/skip.rb +1 -1
  137. data/lib/graphql/schema/directive/specified_by.rb +14 -0
  138. data/lib/graphql/schema/directive/transform.rb +2 -2
  139. data/lib/graphql/schema/directive.rb +33 -21
  140. data/lib/graphql/schema/enum.rb +93 -46
  141. data/lib/graphql/schema/enum_value.rb +4 -21
  142. data/lib/graphql/schema/field/connection_extension.rb +6 -16
  143. data/lib/graphql/schema/field/scope_extension.rb +8 -1
  144. data/lib/graphql/schema/field.rb +432 -337
  145. data/lib/graphql/schema/field_extension.rb +86 -2
  146. data/lib/graphql/schema/find_inherited_value.rb +3 -7
  147. data/lib/graphql/schema/finder.rb +5 -5
  148. data/lib/graphql/schema/has_single_input_argument.rb +156 -0
  149. data/lib/graphql/schema/input_object.rb +88 -90
  150. data/lib/graphql/schema/interface.rb +19 -59
  151. data/lib/graphql/schema/introspection_system.rb +6 -9
  152. data/lib/graphql/schema/late_bound_type.rb +8 -2
  153. data/lib/graphql/schema/list.rb +18 -7
  154. data/lib/graphql/schema/loader.rb +3 -3
  155. data/lib/graphql/schema/member/base_dsl_methods.rb +18 -19
  156. data/lib/graphql/schema/member/build_type.rb +16 -13
  157. data/lib/graphql/schema/member/has_arguments.rb +288 -84
  158. data/lib/graphql/schema/member/has_ast_node.rb +12 -0
  159. data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
  160. data/lib/graphql/schema/member/has_directives.rb +81 -61
  161. data/lib/graphql/schema/member/has_fields.rb +149 -31
  162. data/lib/graphql/schema/member/has_interfaces.rb +143 -0
  163. data/lib/graphql/schema/member/has_validators.rb +32 -6
  164. data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
  165. data/lib/graphql/schema/member/scoped.rb +19 -0
  166. data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
  167. data/lib/graphql/schema/member/validates_input.rb +6 -6
  168. data/lib/graphql/schema/member.rb +1 -6
  169. data/lib/graphql/schema/mutation.rb +0 -9
  170. data/lib/graphql/schema/non_null.rb +7 -7
  171. data/lib/graphql/schema/object.rb +30 -119
  172. data/lib/graphql/schema/printer.rb +23 -25
  173. data/lib/graphql/schema/relay_classic_mutation.rb +13 -90
  174. data/lib/graphql/schema/resolver/has_payload_type.rb +46 -11
  175. data/lib/graphql/schema/resolver.rb +101 -102
  176. data/lib/graphql/schema/scalar.rb +20 -21
  177. data/lib/graphql/schema/subscription.rb +45 -17
  178. data/lib/graphql/schema/timeout.rb +25 -29
  179. data/lib/graphql/schema/type_expression.rb +1 -1
  180. data/lib/graphql/schema/type_membership.rb +21 -4
  181. data/lib/graphql/schema/union.rb +15 -15
  182. data/lib/graphql/schema/unique_within_type.rb +1 -1
  183. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  184. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  185. data/lib/graphql/schema/validator/exclusion_validator.rb +3 -1
  186. data/lib/graphql/schema/validator/format_validator.rb +4 -5
  187. data/lib/graphql/schema/validator/inclusion_validator.rb +3 -1
  188. data/lib/graphql/schema/validator/length_validator.rb +5 -3
  189. data/lib/graphql/schema/validator/numericality_validator.rb +13 -2
  190. data/lib/graphql/schema/validator/required_validator.rb +29 -15
  191. data/lib/graphql/schema/validator.rb +35 -27
  192. data/lib/graphql/schema/warden.rb +259 -132
  193. data/lib/graphql/schema/wrapper.rb +0 -5
  194. data/lib/graphql/schema.rb +658 -989
  195. data/lib/graphql/static_validation/all_rules.rb +3 -1
  196. data/lib/graphql/static_validation/base_visitor.rb +14 -28
  197. data/lib/graphql/static_validation/definition_dependencies.rb +7 -2
  198. data/lib/graphql/static_validation/error.rb +3 -1
  199. data/lib/graphql/static_validation/literal_validator.rb +21 -4
  200. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  201. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
  202. data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
  203. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +13 -13
  204. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
  205. data/lib/graphql/static_validation/rules/fields_will_merge.rb +54 -28
  206. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  207. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  208. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  209. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  210. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  211. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  212. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -3
  213. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -4
  214. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
  215. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
  216. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +13 -7
  217. data/lib/graphql/static_validation/validation_context.rb +16 -6
  218. data/lib/graphql/static_validation/validator.rb +11 -27
  219. data/lib/graphql/static_validation.rb +0 -3
  220. data/lib/graphql/string_encoding_error.rb +13 -3
  221. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +46 -9
  222. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
  223. data/lib/graphql/subscriptions/event.rb +75 -37
  224. data/lib/graphql/subscriptions/serialize.rb +25 -3
  225. data/lib/graphql/subscriptions.rb +59 -47
  226. data/lib/graphql/testing/helpers.rb +129 -0
  227. data/lib/graphql/testing.rb +2 -0
  228. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  229. data/lib/graphql/tracing/active_support_notifications_tracing.rb +6 -20
  230. data/lib/graphql/tracing/appoptics_trace.rb +251 -0
  231. data/lib/graphql/tracing/appoptics_tracing.rb +2 -2
  232. data/lib/graphql/tracing/appsignal_trace.rb +77 -0
  233. data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
  234. data/lib/graphql/tracing/data_dog_trace.rb +183 -0
  235. data/lib/graphql/tracing/data_dog_tracing.rb +25 -15
  236. data/lib/graphql/{execution/instrumentation.rb → tracing/legacy_hooks_trace.rb} +10 -28
  237. data/lib/graphql/tracing/legacy_trace.rb +69 -0
  238. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  239. data/lib/graphql/tracing/notifications_trace.rb +45 -0
  240. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  241. data/lib/graphql/tracing/platform_trace.rb +118 -0
  242. data/lib/graphql/tracing/platform_tracing.rb +46 -49
  243. data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +4 -2
  244. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  245. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  246. data/lib/graphql/tracing/scout_trace.rb +72 -0
  247. data/lib/graphql/tracing/sentry_trace.rb +112 -0
  248. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  249. data/lib/graphql/tracing/trace.rb +76 -0
  250. data/lib/graphql/tracing.rb +20 -41
  251. data/lib/graphql/type_kinds.rb +6 -3
  252. data/lib/graphql/types/big_int.rb +5 -1
  253. data/lib/graphql/types/int.rb +1 -1
  254. data/lib/graphql/types/iso_8601_date.rb +17 -6
  255. data/lib/graphql/types/iso_8601_date_time.rb +12 -1
  256. data/lib/graphql/types/iso_8601_duration.rb +77 -0
  257. data/lib/graphql/types/relay/base_connection.rb +16 -6
  258. data/lib/graphql/types/relay/connection_behaviors.rb +82 -32
  259. data/lib/graphql/types/relay/edge_behaviors.rb +36 -7
  260. data/lib/graphql/types/relay/has_node_field.rb +2 -2
  261. data/lib/graphql/types/relay/has_nodes_field.rb +2 -2
  262. data/lib/graphql/types/relay/node_behaviors.rb +12 -2
  263. data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
  264. data/lib/graphql/types/relay.rb +0 -3
  265. data/lib/graphql/types/string.rb +2 -2
  266. data/lib/graphql/types.rb +1 -0
  267. data/lib/graphql/unauthorized_error.rb +1 -1
  268. data/lib/graphql/version.rb +1 -1
  269. data/lib/graphql.rb +33 -95
  270. data/readme.md +13 -6
  271. metadata +102 -185
  272. data/lib/graphql/analysis/analyze_query.rb +0 -98
  273. data/lib/graphql/analysis/field_usage.rb +0 -45
  274. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  275. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  276. data/lib/graphql/analysis/query_complexity.rb +0 -88
  277. data/lib/graphql/analysis/query_depth.rb +0 -43
  278. data/lib/graphql/analysis/reducer_state.rb +0 -48
  279. data/lib/graphql/argument.rb +0 -131
  280. data/lib/graphql/authorization.rb +0 -82
  281. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  282. data/lib/graphql/backwards_compatibility.rb +0 -61
  283. data/lib/graphql/base_type.rb +0 -230
  284. data/lib/graphql/boolean_type.rb +0 -2
  285. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  286. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  287. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  288. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  289. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  290. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  291. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  292. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  293. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  294. data/lib/graphql/compatibility.rb +0 -5
  295. data/lib/graphql/define/assign_argument.rb +0 -12
  296. data/lib/graphql/define/assign_connection.rb +0 -13
  297. data/lib/graphql/define/assign_enum_value.rb +0 -18
  298. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  299. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  300. data/lib/graphql/define/assign_object_field.rb +0 -42
  301. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  302. data/lib/graphql/define/instance_definable.rb +0 -240
  303. data/lib/graphql/define/no_definition_error.rb +0 -7
  304. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  305. data/lib/graphql/define/type_definer.rb +0 -31
  306. data/lib/graphql/define.rb +0 -31
  307. data/lib/graphql/deprecated_dsl.rb +0 -47
  308. data/lib/graphql/deprecation.rb +0 -13
  309. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  310. data/lib/graphql/directive/include_directive.rb +0 -2
  311. data/lib/graphql/directive/skip_directive.rb +0 -2
  312. data/lib/graphql/directive.rb +0 -111
  313. data/lib/graphql/enum_type.rb +0 -129
  314. data/lib/graphql/execution/execute.rb +0 -333
  315. data/lib/graphql/execution/flatten.rb +0 -40
  316. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  317. data/lib/graphql/execution/typecast.rb +0 -50
  318. data/lib/graphql/field/resolve.rb +0 -59
  319. data/lib/graphql/field.rb +0 -226
  320. data/lib/graphql/filter.rb +0 -53
  321. data/lib/graphql/float_type.rb +0 -2
  322. data/lib/graphql/function.rb +0 -128
  323. data/lib/graphql/id_type.rb +0 -2
  324. data/lib/graphql/input_object_type.rb +0 -138
  325. data/lib/graphql/int_type.rb +0 -2
  326. data/lib/graphql/interface_type.rb +0 -72
  327. data/lib/graphql/internal_representation/document.rb +0 -27
  328. data/lib/graphql/internal_representation/node.rb +0 -206
  329. data/lib/graphql/internal_representation/print.rb +0 -51
  330. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  331. data/lib/graphql/internal_representation/scope.rb +0 -88
  332. data/lib/graphql/internal_representation/visit.rb +0 -36
  333. data/lib/graphql/internal_representation.rb +0 -7
  334. data/lib/graphql/language/lexer.rl +0 -262
  335. data/lib/graphql/language/parser.y +0 -543
  336. data/lib/graphql/list_type.rb +0 -80
  337. data/lib/graphql/non_null_type.rb +0 -71
  338. data/lib/graphql/object_type.rb +0 -130
  339. data/lib/graphql/query/arguments.rb +0 -189
  340. data/lib/graphql/query/arguments_cache.rb +0 -24
  341. data/lib/graphql/query/executor.rb +0 -52
  342. data/lib/graphql/query/literal_input.rb +0 -136
  343. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  344. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  345. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  346. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  347. data/lib/graphql/query/serial_execution.rb +0 -40
  348. data/lib/graphql/relay/array_connection.rb +0 -83
  349. data/lib/graphql/relay/base_connection.rb +0 -189
  350. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  351. data/lib/graphql/relay/connection_resolve.rb +0 -43
  352. data/lib/graphql/relay/connection_type.rb +0 -41
  353. data/lib/graphql/relay/edge.rb +0 -27
  354. data/lib/graphql/relay/edge_type.rb +0 -19
  355. data/lib/graphql/relay/edges_instrumentation.rb +0 -40
  356. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  357. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  358. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  359. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  360. data/lib/graphql/relay/mutation/result.rb +0 -38
  361. data/lib/graphql/relay/mutation.rb +0 -106
  362. data/lib/graphql/relay/node.rb +0 -39
  363. data/lib/graphql/relay/page_info.rb +0 -7
  364. data/lib/graphql/relay/relation_connection.rb +0 -188
  365. data/lib/graphql/relay/type_extensions.rb +0 -32
  366. data/lib/graphql/scalar_type.rb +0 -91
  367. data/lib/graphql/schema/base_64_bp.rb +0 -26
  368. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  369. data/lib/graphql/schema/default_parse_error.rb +0 -10
  370. data/lib/graphql/schema/default_type_error.rb +0 -17
  371. data/lib/graphql/schema/member/accepts_definition.rb +0 -152
  372. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -31
  373. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  374. data/lib/graphql/schema/middleware_chain.rb +0 -82
  375. data/lib/graphql/schema/possible_types.rb +0 -44
  376. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  377. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  378. data/lib/graphql/schema/traversal.rb +0 -228
  379. data/lib/graphql/schema/validation.rb +0 -313
  380. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  381. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  382. data/lib/graphql/static_validation/type_stack.rb +0 -216
  383. data/lib/graphql/string_type.rb +0 -2
  384. data/lib/graphql/subscriptions/instrumentation.rb +0 -79
  385. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  386. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  387. data/lib/graphql/types/relay/default_relay.rb +0 -27
  388. data/lib/graphql/types/relay/node_field.rb +0 -25
  389. data/lib/graphql/types/relay/nodes_field.rb +0 -27
  390. data/lib/graphql/union_type.rb +0 -115
  391. data/lib/graphql/upgrader/member.rb +0 -937
  392. data/lib/graphql/upgrader/schema.rb +0 -38
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Tracing
5
+ module ScoutTrace
6
+ include PlatformTrace
7
+
8
+ INSTRUMENT_OPTS = { scope: true }
9
+
10
+ # @param set_transaction_name [Boolean] If true, the GraphQL operation name will be used as the transaction name.
11
+ # This is not advised if you run more than one query per HTTP request, for example, with `graphql-client` or multiplexing.
12
+ # It can also be specified per-query with `context[:set_scout_transaction_name]`.
13
+ def initialize(set_transaction_name: false, **_rest)
14
+ self.class.include(ScoutApm::Tracer)
15
+ @set_transaction_name = set_transaction_name
16
+ super
17
+ end
18
+
19
+ {
20
+ "lex" => "lex.graphql",
21
+ "parse" => "parse.graphql",
22
+ "validate" => "validate.graphql",
23
+ "analyze_query" => "analyze.graphql",
24
+ "analyze_multiplex" => "analyze.graphql",
25
+ "execute_multiplex" => "execute.graphql",
26
+ "execute_query" => "execute.graphql",
27
+ "execute_query_lazy" => "execute.graphql",
28
+ }.each do |trace_method, platform_key|
29
+ module_eval <<-RUBY, __FILE__, __LINE__
30
+ def #{trace_method}(**data)
31
+ #{
32
+ if trace_method == "execute_query"
33
+ <<-RUBY
34
+ set_this_txn_name = data[:query].context[:set_scout_transaction_name]
35
+ if set_this_txn_name == true || (set_this_txn_name.nil? && @set_transaction_name)
36
+ ScoutApm::Transaction.rename(transaction_name(data[:query]))
37
+ end
38
+ RUBY
39
+ end
40
+ }
41
+
42
+ self.class.instrument("GraphQL", "#{platform_key}", INSTRUMENT_OPTS) do
43
+ super
44
+ end
45
+ end
46
+ RUBY
47
+ end
48
+
49
+ def platform_execute_field(platform_key, &block)
50
+ self.class.instrument("GraphQL", platform_key, INSTRUMENT_OPTS, &block)
51
+ end
52
+
53
+ def platform_authorized(platform_key, &block)
54
+ self.class.instrument("GraphQL", platform_key, INSTRUMENT_OPTS, &block)
55
+ end
56
+
57
+ alias :platform_resolve_type :platform_authorized
58
+
59
+ def platform_field_key(field)
60
+ field.path
61
+ end
62
+
63
+ def platform_authorized_key(type)
64
+ "#{type.graphql_name}.authorized"
65
+ end
66
+
67
+ def platform_resolve_type_key(type)
68
+ "#{type.graphql_name}.resolve_type"
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Tracing
5
+ module SentryTrace
6
+ include PlatformTrace
7
+
8
+ # @param set_transaction_name [Boolean] If true, the GraphQL operation name will be used as the transaction name.
9
+ # This is not advised if you run more than one query per HTTP request, for example, with `graphql-client` or multiplexing.
10
+ # It can also be specified per-query with `context[:set_sentry_transaction_name]`.
11
+ def initialize(set_transaction_name: false, **_rest)
12
+ @set_transaction_name = set_transaction_name
13
+ super
14
+ end
15
+
16
+ def execute_query(**data)
17
+ set_this_txn_name = data[:query].context[:set_sentry_transaction_name]
18
+ if set_this_txn_name == true || (set_this_txn_name.nil? && @set_transaction_name)
19
+ Sentry.configure_scope do |scope|
20
+ scope.set_transaction_name(transaction_name(data[:query]))
21
+ end
22
+ end
23
+ instrument_execution("graphql.execute", "execute_query", data) { super }
24
+ end
25
+
26
+ {
27
+ "lex" => "graphql.lex",
28
+ "parse" => "graphql.parse",
29
+ "validate" => "graphql.validate",
30
+ "analyze_query" => "graphql.analyze",
31
+ "analyze_multiplex" => "graphql.analyze_multiplex",
32
+ "execute_multiplex" => "graphql.execute_multiplex",
33
+ "execute_query_lazy" => "graphql.execute"
34
+ }.each do |trace_method, platform_key|
35
+ module_eval <<-RUBY, __FILE__, __LINE__
36
+ def #{trace_method}(**data)
37
+ instrument_execution("#{platform_key}", "#{trace_method}", data) { super }
38
+ end
39
+ RUBY
40
+ end
41
+
42
+ def platform_execute_field(platform_key, &block)
43
+ instrument_execution(platform_key, "execute_field", &block)
44
+ end
45
+
46
+ def platform_execute_field_lazy(platform_key, &block)
47
+ instrument_execution(platform_key, "execute_field_lazy", &block)
48
+ end
49
+
50
+ def platform_authorized(platform_key, &block)
51
+ instrument_execution(platform_key, "authorized", &block)
52
+ end
53
+
54
+ def platform_authorized_lazy(platform_key, &block)
55
+ instrument_execution(platform_key, "authorized_lazy", &block)
56
+ end
57
+
58
+ def platform_resolve_type(platform_key, &block)
59
+ instrument_execution(platform_key, "resolve_type", &block)
60
+ end
61
+
62
+ def platform_resolve_type_lazy(platform_key, &block)
63
+ instrument_execution(platform_key, "resolve_type_lazy", &block)
64
+ end
65
+
66
+ def platform_field_key(field)
67
+ "graphql.field.#{field.path}"
68
+ end
69
+
70
+ def platform_authorized_key(type)
71
+ "graphql.authorized.#{type.graphql_name}"
72
+ end
73
+
74
+ def platform_resolve_type_key(type)
75
+ "graphql.resolve_type.#{type.graphql_name}"
76
+ end
77
+
78
+ private
79
+
80
+ def instrument_execution(platform_key, trace_method, data=nil, &block)
81
+ return yield unless Sentry.initialized?
82
+
83
+ Sentry.with_child_span(op: platform_key, start_timestamp: Sentry.utc_now.to_f) do |span|
84
+ result = yield
85
+ return result unless span
86
+
87
+ span.finish
88
+ if trace_method == "execute_multiplex" && data.key?(:multiplex)
89
+ operation_names = data[:multiplex].queries.map{|q| operation_name(q) }
90
+ span.set_description(operation_names.join(", "))
91
+ elsif trace_method == "execute_query" && data.key?(:query)
92
+ span.set_description(operation_name(data[:query]))
93
+ span.set_data('graphql.document', data[:query].query_string)
94
+ span.set_data('graphql.operation.name', data[:query].selected_operation_name) if data[:query].selected_operation_name
95
+ span.set_data('graphql.operation.type', data[:query].selected_operation.operation_type)
96
+ end
97
+
98
+ result
99
+ end
100
+ end
101
+
102
+ def operation_name(query)
103
+ selected_op = query.selected_operation
104
+ if selected_op
105
+ [selected_op.operation_type, selected_op.name].compact.join(' ')
106
+ else
107
+ 'GraphQL Operation'
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Tracing
5
+ module StatsdTrace
6
+ include PlatformTrace
7
+
8
+ # @param statsd [Object] A statsd client
9
+ def initialize(statsd:, **rest)
10
+ @statsd = statsd
11
+ super(**rest)
12
+ end
13
+
14
+ {
15
+ 'lex' => "graphql.lex",
16
+ 'parse' => "graphql.parse",
17
+ 'validate' => "graphql.validate",
18
+ 'analyze_query' => "graphql.analyze_query",
19
+ 'analyze_multiplex' => "graphql.analyze_multiplex",
20
+ 'execute_multiplex' => "graphql.execute_multiplex",
21
+ 'execute_query' => "graphql.execute_query",
22
+ 'execute_query_lazy' => "graphql.execute_query_lazy",
23
+ }.each do |trace_method, platform_key|
24
+ module_eval <<-RUBY, __FILE__, __LINE__
25
+ def #{trace_method}(**data)
26
+ @statsd.time("#{platform_key}") do
27
+ super
28
+ end
29
+ end
30
+ RUBY
31
+ end
32
+
33
+ def platform_execute_field(platform_key, &block)
34
+ @statsd.time(platform_key, &block)
35
+ end
36
+
37
+ def platform_authorized(key, &block)
38
+ @statsd.time(key, &block)
39
+ end
40
+
41
+ alias :platform_resolve_type :platform_authorized
42
+
43
+ def platform_field_key(field)
44
+ "graphql.#{field.path}"
45
+ end
46
+
47
+ def platform_authorized_key(type)
48
+ "graphql.authorized.#{type.graphql_name}"
49
+ end
50
+
51
+ def platform_resolve_type_key(type)
52
+ "graphql.resolve_type.#{type.graphql_name}"
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Tracing
4
+ # This is the base class for a `trace` instance whose methods are called during query execution.
5
+ # "Trace modes" are subclasses of this with custom tracing modules mixed in.
6
+ #
7
+ # A trace module may implement any of the methods on `Trace`, being sure to call `super`
8
+ # to continue any tracing hooks and call the actual runtime behavior. See {GraphQL::Backtrace::Trace} for example.
9
+ #
10
+ class Trace
11
+ # @param multiplex [GraphQL::Execution::Multiplex, nil]
12
+ # @param query [GraphQL::Query, nil]
13
+ def initialize(multiplex: nil, query: nil, **_options)
14
+ @multiplex = multiplex
15
+ @query = query
16
+ end
17
+
18
+ # The Ruby parser doesn't call this method (`graphql/c_parser` does.)
19
+ def lex(query_string:)
20
+ yield
21
+ end
22
+
23
+ def parse(query_string:)
24
+ yield
25
+ end
26
+
27
+ def validate(query:, validate:)
28
+ yield
29
+ end
30
+
31
+ def analyze_multiplex(multiplex:)
32
+ yield
33
+ end
34
+
35
+ def analyze_query(query:)
36
+ yield
37
+ end
38
+
39
+ def execute_multiplex(multiplex:)
40
+ yield
41
+ end
42
+
43
+ def execute_query(query:)
44
+ yield
45
+ end
46
+
47
+ def execute_query_lazy(query:, multiplex:)
48
+ yield
49
+ end
50
+
51
+ def execute_field(field:, query:, ast_node:, arguments:, object:)
52
+ yield
53
+ end
54
+
55
+ def execute_field_lazy(field:, query:, ast_node:, arguments:, object:)
56
+ yield
57
+ end
58
+
59
+ def authorized(query:, type:, object:)
60
+ yield
61
+ end
62
+
63
+ def authorized_lazy(query:, type:, object:)
64
+ yield
65
+ end
66
+
67
+ def resolve_type(query:, type:, object:)
68
+ yield
69
+ end
70
+
71
+ def resolve_type_lazy(query:, type:, object:)
72
+ yield
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,4 +1,9 @@
1
1
  # frozen_string_literal: true
2
+ require "graphql/tracing/trace"
3
+ require "graphql/tracing/legacy_trace"
4
+ require "graphql/tracing/legacy_hooks_trace"
5
+
6
+ # Legacy tracing:
2
7
  require "graphql/tracing/active_support_notifications_tracing"
3
8
  require "graphql/tracing/platform_tracing"
4
9
  require "graphql/tracing/appoptics_tracing"
@@ -6,55 +11,29 @@ require "graphql/tracing/appsignal_tracing"
6
11
  require "graphql/tracing/data_dog_tracing"
7
12
  require "graphql/tracing/new_relic_tracing"
8
13
  require "graphql/tracing/scout_tracing"
9
- require "graphql/tracing/skylight_tracing"
10
14
  require "graphql/tracing/statsd_tracing"
11
15
  require "graphql/tracing/prometheus_tracing"
12
16
 
17
+ # New Tracing:
18
+ require "graphql/tracing/active_support_notifications_trace"
19
+ require "graphql/tracing/platform_trace"
20
+ require "graphql/tracing/appoptics_trace"
21
+ require "graphql/tracing/appsignal_trace"
22
+ require "graphql/tracing/data_dog_trace"
23
+ require "graphql/tracing/new_relic_trace"
24
+ require "graphql/tracing/notifications_trace"
25
+ require "graphql/tracing/sentry_trace"
26
+ require "graphql/tracing/scout_trace"
27
+ require "graphql/tracing/statsd_trace"
28
+ require "graphql/tracing/prometheus_trace"
13
29
  if defined?(PrometheusExporter::Server)
14
- require "graphql/tracing/prometheus_tracing/graphql_collector"
30
+ require "graphql/tracing/prometheus_trace/graphql_collector"
15
31
  end
16
32
 
17
33
  module GraphQL
18
- # Library entry point for performance metric reporting.
19
- #
20
- # @example Sending custom events
21
- # query.trace("my_custom_event", { ... }) do
22
- # # do stuff ...
23
- # end
24
- #
25
- # @example Adding a tracer to a schema
26
- # class MySchema < GraphQL::Schema
27
- # tracer MyTracer # <= responds to .trace(key, data, &block)
28
- # end
29
- #
30
- # @example Adding a tracer to a single query
31
- # MySchema.execute(query_str, context: { backtrace: true })
32
- #
33
- # Events:
34
- #
35
- # Key | Metadata
36
- # ----|---------
37
- # lex | `{ query_string: String }`
38
- # parse | `{ query_string: String }`
39
- # validate | `{ query: GraphQL::Query, validate: Boolean }`
40
- # analyze_multiplex | `{ multiplex: GraphQL::Execution::Multiplex }`
41
- # analyze_query | `{ query: GraphQL::Query }`
42
- # execute_multiplex | `{ multiplex: GraphQL::Execution::Multiplex }`
43
- # execute_query | `{ query: GraphQL::Query }`
44
- # execute_query_lazy | `{ query: GraphQL::Query?, multiplex: GraphQL::Execution::Multiplex? }`
45
- # execute_field | `{ owner: Class, field: GraphQL::Schema::Field, query: GraphQL::Query, path: Array<String, Integer>, ast_node: GraphQL::Language::Nodes::Field}`
46
- # execute_field_lazy | `{ owner: Class, field: GraphQL::Schema::Field, query: GraphQL::Query, path: Array<String, Integer>, ast_node: GraphQL::Language::Nodes::Field}`
47
- # authorized | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
48
- # authorized_lazy | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
49
- # resolve_type | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
50
- # resolve_type_lazy | `{ context: GraphQL::Query::Context, type: Class, object: Object, path: Array<String, Integer> }`
51
- #
52
- # Note that `execute_field` and `execute_field_lazy` receive different data in different settings:
53
- #
54
- # - When using {GraphQL::Execution::Interpreter}, they receive `{field:, path:, query:}`
55
- # - Otherwise, they receive `{context: ...}`
56
- #
57
34
  module Tracing
35
+ NullTrace = Trace.new
36
+
58
37
  # Objects may include traceable to gain a `.trace(...)` method.
59
38
  # The object must have a `@tracers` ivar of type `Array<<#trace(k, d, &b)>>`.
60
39
  # @api private
@@ -5,12 +5,13 @@ module GraphQL
5
5
  # These objects are singletons, eg `GraphQL::TypeKinds::UNION`, `GraphQL::TypeKinds::SCALAR`.
6
6
  class TypeKind
7
7
  attr_reader :name, :description
8
- def initialize(name, abstract: false, fields: false, wraps: false, input: false, description: nil)
8
+ def initialize(name, abstract: false, leaf: false, fields: false, wraps: false, input: false, description: nil)
9
9
  @name = name
10
10
  @abstract = abstract
11
11
  @fields = fields
12
12
  @wraps = wraps
13
13
  @input = input
14
+ @leaf = leaf
14
15
  @composite = fields? || abstract?
15
16
  @description = description
16
17
  end
@@ -27,6 +28,8 @@ module GraphQL
27
28
  # Is this TypeKind a valid query input?
28
29
  def input?; @input; end
29
30
  def to_s; @name; end
31
+ # Is this TypeKind a primitive value?
32
+ def leaf?; @leaf; end
30
33
  # Is this TypeKind composed of many values?
31
34
  def composite?; @composite; end
32
35
 
@@ -64,11 +67,11 @@ module GraphQL
64
67
  end
65
68
 
66
69
  TYPE_KINDS = [
67
- SCALAR = TypeKind.new("SCALAR", input: true, description: 'Indicates this type is a scalar.'),
70
+ SCALAR = TypeKind.new("SCALAR", input: true, leaf: true, description: 'Indicates this type is a scalar.'),
68
71
  OBJECT = TypeKind.new("OBJECT", fields: true, description: 'Indicates this type is an object. `fields` and `interfaces` are valid fields.'),
69
72
  INTERFACE = TypeKind.new("INTERFACE", abstract: true, fields: true, description: 'Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.'),
70
73
  UNION = TypeKind.new("UNION", abstract: true, description: 'Indicates this type is a union. `possibleTypes` is a valid field.'),
71
- ENUM = TypeKind.new("ENUM", input: true, description: 'Indicates this type is an enum. `enumValues` is a valid field.'),
74
+ ENUM = TypeKind.new("ENUM", input: true, leaf: true, description: 'Indicates this type is an enum. `enumValues` is a valid field.'),
72
75
  INPUT_OBJECT = TypeKind.new("INPUT_OBJECT", input: true, description: 'Indicates this type is an input object. `inputFields` is a valid field.'),
73
76
  LIST = TypeKind.new("LIST", wraps: true, description: 'Indicates this type is a list. `ofType` is a valid field.'),
74
77
  NON_NULL = TypeKind.new("NON_NULL", wraps: true, description: 'Indicates this type is a non-null. `ofType` is a valid field.'),
@@ -6,7 +6,7 @@ module GraphQL
6
6
  description "Represents non-fractional signed whole numeric values. Since the value may exceed the size of a 32-bit integer, it's encoded as a string."
7
7
 
8
8
  def self.coerce_input(value, _ctx)
9
- value && Integer(value)
9
+ value && parse_int(value)
10
10
  rescue ArgumentError
11
11
  nil
12
12
  end
@@ -14,6 +14,10 @@ module GraphQL
14
14
  def self.coerce_result(value, _ctx)
15
15
  value.to_i.to_s
16
16
  end
17
+
18
+ def self.parse_int(value)
19
+ value.is_a?(Numeric) ? value : Integer(value, 10)
20
+ end
17
21
  end
18
22
  end
19
23
  end
@@ -25,7 +25,7 @@ module GraphQL
25
25
  if value >= MIN && value <= MAX
26
26
  value
27
27
  else
28
- err = GraphQL::IntegerEncodingError.new(value)
28
+ err = GraphQL::IntegerEncodingError.new(value, context: ctx)
29
29
  ctx.schema.type_error(err, ctx)
30
30
  end
31
31
  end
@@ -14,6 +14,7 @@ module GraphQL
14
14
  # own Date type.
15
15
  class ISO8601Date < GraphQL::Schema::Scalar
16
16
  description "An ISO 8601-encoded date"
17
+ specified_by_url "https://tools.ietf.org/html/rfc3339"
17
18
 
18
19
  # @param value [Date,Time,DateTime,String]
19
20
  # @return [String]
@@ -21,13 +22,23 @@ module GraphQL
21
22
  Date.parse(value.to_s).iso8601
22
23
  end
23
24
 
24
- # @param str_value [String]
25
- # @return [Date]
26
- def self.coerce_input(str_value, _ctx)
27
- Date.iso8601(str_value)
25
+ # @param str_value [String, Date, DateTime, Time]
26
+ # @return [Date, nil]
27
+ def self.coerce_input(value, ctx)
28
+ if value.is_a?(::Date)
29
+ value
30
+ elsif value.is_a?(::DateTime)
31
+ value.to_date
32
+ elsif value.is_a?(::Time)
33
+ value.to_date
34
+ elsif value.nil?
35
+ nil
36
+ else
37
+ Date.iso8601(value)
38
+ end
28
39
  rescue ArgumentError, TypeError
29
- # Invalid input
30
- nil
40
+ err = GraphQL::DateEncodingError.new(value)
41
+ ctx.schema.type_error(err, ctx)
31
42
  end
32
43
  end
33
44
  end
@@ -17,6 +17,7 @@ module GraphQL
17
17
  # own DateTime type.
18
18
  class ISO8601DateTime < GraphQL::Schema::Scalar
19
19
  description "An ISO 8601-encoded datetime"
20
+ specified_by_url "https://tools.ietf.org/html/rfc3339"
20
21
 
21
22
  # It's not compatible with Rails' default,
22
23
  # i.e. ActiveSupport::JSON::Encoder.time_precision (3 by default)
@@ -54,7 +55,17 @@ module GraphQL
54
55
  Time.iso8601(str_value)
55
56
  rescue ArgumentError, TypeError
56
57
  begin
57
- Date.iso8601(str_value).to_time
58
+ dt = Date.iso8601(str_value).to_time
59
+ # For compatibility, continue accepting dates given without times
60
+ # But without this, it would zero out given any time part of `str_value` (hours and/or minutes)
61
+ if dt.iso8601.start_with?(str_value)
62
+ dt
63
+ elsif str_value.length == 8 && str_value.match?(/\A\d{8}\Z/)
64
+ # Allow dates that are missing the "-". eg. "20220404"
65
+ dt
66
+ else
67
+ nil
68
+ end
58
69
  rescue ArgumentError, TypeError
59
70
  # Invalid input
60
71
  nil
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module Types
4
+ # This scalar takes `Duration`s and transmits them as strings,
5
+ # using ISO 8601 format. ActiveSupport >= 5.0 must be loaded to use
6
+ # this scalar.
7
+ #
8
+ # Use it for fields or arguments as follows:
9
+ #
10
+ # field :age, GraphQL::Types::ISO8601Duration, null: false
11
+ #
12
+ # argument :interval, GraphQL::Types::ISO8601Duration, null: false
13
+ #
14
+ # Alternatively, use this built-in scalar as inspiration for your
15
+ # own Duration type.
16
+ class ISO8601Duration < GraphQL::Schema::Scalar
17
+ description "An ISO 8601-encoded duration"
18
+
19
+ # @return [Integer, nil]
20
+ def self.seconds_precision
21
+ # ActiveSupport::Duration precision defaults to whatever input was given
22
+ @seconds_precision
23
+ end
24
+
25
+ # @param [Integer, nil] value
26
+ def self.seconds_precision=(value)
27
+ @seconds_precision = value
28
+ end
29
+
30
+ # @param value [ActiveSupport::Duration, String]
31
+ # @return [String]
32
+ # @raise [GraphQL::Error] if ActiveSupport::Duration is not defined or if an incompatible object is passed
33
+ def self.coerce_result(value, _ctx)
34
+ unless defined?(ActiveSupport::Duration)
35
+ raise GraphQL::Error, "ActiveSupport >= 5.0 must be loaded to use the built-in ISO8601Duration type."
36
+ end
37
+
38
+ begin
39
+ case value
40
+ when ActiveSupport::Duration
41
+ value.iso8601(precision: seconds_precision)
42
+ when ::String
43
+ ActiveSupport::Duration.parse(value).iso8601(precision: seconds_precision)
44
+ else
45
+ # Try calling as ActiveSupport::Duration compatible as a fallback
46
+ value.iso8601(precision: seconds_precision)
47
+ end
48
+ rescue StandardError => error
49
+ raise GraphQL::Error, "An incompatible object (#{value.class}) was given to #{self}. Make sure that only ActiveSupport::Durations and well-formatted Strings are used with this type. (#{error.message})"
50
+ end
51
+ end
52
+
53
+ # @param value [String, ActiveSupport::Duration]
54
+ # @return [ActiveSupport::Duration, nil]
55
+ # @raise [GraphQL::Error] if ActiveSupport::Duration is not defined
56
+ # @raise [GraphQL::DurationEncodingError] if duration cannot be parsed
57
+ def self.coerce_input(value, ctx)
58
+ unless defined?(ActiveSupport::Duration)
59
+ raise GraphQL::Error, "ActiveSupport >= 5.0 must be loaded to use the built-in ISO8601Duration type."
60
+ end
61
+
62
+ begin
63
+ if value.is_a?(ActiveSupport::Duration)
64
+ value
65
+ elsif value.nil?
66
+ nil
67
+ else
68
+ ActiveSupport::Duration.parse(value)
69
+ end
70
+ rescue ArgumentError, TypeError
71
+ err = GraphQL::DurationEncodingError.new(value)
72
+ ctx.schema.type_error(err, ctx)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -10,6 +10,8 @@ module GraphQL
10
10
  # so you can extend your own `BaseObject` instead of `GraphQL::Schema::Object`.
11
11
  #
12
12
  # @example Implementation a connection and edge
13
+ # class BaseObject < GraphQL::Schema::Object; end
14
+ #
13
15
  # # Given some object in your app ...
14
16
  # class Types::Post < BaseObject
15
17
  # end
@@ -20,14 +22,22 @@ module GraphQL
20
22
  #
21
23
  # # Then extend them for the object in your app
22
24
  # class Types::PostEdge < Types::BaseEdge
23
- # node_type(Types::Post)
25
+ # node_type Types::Post
24
26
  # end
27
+ #
25
28
  # class Types::PostConnection < Types::BaseConnection
26
- # edge_type(Types::PostEdge)
27
- # edges_nullable(true)
28
- # edge_nullable(true)
29
- # node_nullable(true)
30
- # has_nodes_field(true)
29
+ # edge_type Types::PostEdge,
30
+ # edges_nullable: true,
31
+ # edge_nullable: true,
32
+ # node_nullable: true,
33
+ # nodes_field: true
34
+ #
35
+ # # Alternatively, you can call the class methods followed by your edge type
36
+ # # edges_nullable true
37
+ # # edge_nullable true
38
+ # # node_nullable true
39
+ # # has_nodes_field true
40
+ # # edge_type Types::PostEdge
31
41
  # end
32
42
  #
33
43
  # @see Relay::BaseEdge for edge types