graphql_cody 1.13.0

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.
Files changed (444) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +5 -0
  3. data/MIT-LICENSE +20 -0
  4. data/lib/generators/graphql/core.rb +74 -0
  5. data/lib/generators/graphql/enum_generator.rb +33 -0
  6. data/lib/generators/graphql/install_generator.rb +190 -0
  7. data/lib/generators/graphql/interface_generator.rb +27 -0
  8. data/lib/generators/graphql/loader_generator.rb +21 -0
  9. data/lib/generators/graphql/mutation_generator.rb +55 -0
  10. data/lib/generators/graphql/object_generator.rb +79 -0
  11. data/lib/generators/graphql/relay.rb +63 -0
  12. data/lib/generators/graphql/relay_generator.rb +21 -0
  13. data/lib/generators/graphql/scalar_generator.rb +20 -0
  14. data/lib/generators/graphql/templates/base_argument.erb +6 -0
  15. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  16. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  17. data/lib/generators/graphql/templates/base_enum.erb +6 -0
  18. data/lib/generators/graphql/templates/base_field.erb +7 -0
  19. data/lib/generators/graphql/templates/base_input_object.erb +7 -0
  20. data/lib/generators/graphql/templates/base_interface.erb +9 -0
  21. data/lib/generators/graphql/templates/base_mutation.erb +10 -0
  22. data/lib/generators/graphql/templates/base_object.erb +7 -0
  23. data/lib/generators/graphql/templates/base_scalar.erb +6 -0
  24. data/lib/generators/graphql/templates/base_union.erb +6 -0
  25. data/lib/generators/graphql/templates/enum.erb +7 -0
  26. data/lib/generators/graphql/templates/graphql_controller.erb +52 -0
  27. data/lib/generators/graphql/templates/interface.erb +8 -0
  28. data/lib/generators/graphql/templates/loader.erb +19 -0
  29. data/lib/generators/graphql/templates/mutation.erb +16 -0
  30. data/lib/generators/graphql/templates/mutation_type.erb +12 -0
  31. data/lib/generators/graphql/templates/node_type.erb +9 -0
  32. data/lib/generators/graphql/templates/object.erb +8 -0
  33. data/lib/generators/graphql/templates/query_type.erb +15 -0
  34. data/lib/generators/graphql/templates/scalar.erb +15 -0
  35. data/lib/generators/graphql/templates/schema.erb +27 -0
  36. data/lib/generators/graphql/templates/union.erb +7 -0
  37. data/lib/generators/graphql/type_generator.rb +98 -0
  38. data/lib/generators/graphql/union_generator.rb +33 -0
  39. data/lib/graphql/analysis/analyze_query.rb +98 -0
  40. data/lib/graphql/analysis/ast/analyzer.rb +84 -0
  41. data/lib/graphql/analysis/ast/field_usage.rb +51 -0
  42. data/lib/graphql/analysis/ast/max_query_complexity.rb +23 -0
  43. data/lib/graphql/analysis/ast/max_query_depth.rb +22 -0
  44. data/lib/graphql/analysis/ast/query_complexity.rb +230 -0
  45. data/lib/graphql/analysis/ast/query_depth.rb +56 -0
  46. data/lib/graphql/analysis/ast/visitor.rb +268 -0
  47. data/lib/graphql/analysis/ast.rb +91 -0
  48. data/lib/graphql/analysis/field_usage.rb +45 -0
  49. data/lib/graphql/analysis/max_query_complexity.rb +26 -0
  50. data/lib/graphql/analysis/max_query_depth.rb +26 -0
  51. data/lib/graphql/analysis/query_complexity.rb +88 -0
  52. data/lib/graphql/analysis/query_depth.rb +43 -0
  53. data/lib/graphql/analysis/reducer_state.rb +48 -0
  54. data/lib/graphql/analysis.rb +9 -0
  55. data/lib/graphql/analysis_error.rb +5 -0
  56. data/lib/graphql/argument.rb +131 -0
  57. data/lib/graphql/authorization.rb +82 -0
  58. data/lib/graphql/backtrace/inspect_result.rb +50 -0
  59. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  60. data/lib/graphql/backtrace/table.rb +159 -0
  61. data/lib/graphql/backtrace/traced_error.rb +54 -0
  62. data/lib/graphql/backtrace/tracer.rb +81 -0
  63. data/lib/graphql/backtrace.rb +64 -0
  64. data/lib/graphql/backwards_compatibility.rb +61 -0
  65. data/lib/graphql/base_type.rb +230 -0
  66. data/lib/graphql/boolean_type.rb +2 -0
  67. data/lib/graphql/coercion_error.rb +13 -0
  68. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +53 -0
  69. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +200 -0
  70. data/lib/graphql/compatibility/execution_specification.rb +436 -0
  71. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +111 -0
  72. data/lib/graphql/compatibility/lazy_execution_specification.rb +215 -0
  73. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +87 -0
  74. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +79 -0
  75. data/lib/graphql/compatibility/query_parser_specification.rb +266 -0
  76. data/lib/graphql/compatibility/schema_parser_specification.rb +682 -0
  77. data/lib/graphql/compatibility.rb +5 -0
  78. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  79. data/lib/graphql/dataloader/request.rb +19 -0
  80. data/lib/graphql/dataloader/request_all.rb +19 -0
  81. data/lib/graphql/dataloader/source.rb +155 -0
  82. data/lib/graphql/dataloader.rb +308 -0
  83. data/lib/graphql/define/assign_argument.rb +12 -0
  84. data/lib/graphql/define/assign_connection.rb +13 -0
  85. data/lib/graphql/define/assign_enum_value.rb +18 -0
  86. data/lib/graphql/define/assign_global_id_field.rb +11 -0
  87. data/lib/graphql/define/assign_mutation_function.rb +34 -0
  88. data/lib/graphql/define/assign_object_field.rb +42 -0
  89. data/lib/graphql/define/defined_object_proxy.rb +53 -0
  90. data/lib/graphql/define/instance_definable.rb +240 -0
  91. data/lib/graphql/define/no_definition_error.rb +7 -0
  92. data/lib/graphql/define/non_null_with_bang.rb +16 -0
  93. data/lib/graphql/define/type_definer.rb +31 -0
  94. data/lib/graphql/define.rb +31 -0
  95. data/lib/graphql/deprecated_dsl.rb +55 -0
  96. data/lib/graphql/deprecation.rb +9 -0
  97. data/lib/graphql/dig.rb +19 -0
  98. data/lib/graphql/directive/deprecated_directive.rb +2 -0
  99. data/lib/graphql/directive/include_directive.rb +2 -0
  100. data/lib/graphql/directive/skip_directive.rb +2 -0
  101. data/lib/graphql/directive.rb +107 -0
  102. data/lib/graphql/enum_type.rb +133 -0
  103. data/lib/graphql/execution/directive_checks.rb +37 -0
  104. data/lib/graphql/execution/errors.rb +163 -0
  105. data/lib/graphql/execution/execute.rb +333 -0
  106. data/lib/graphql/execution/flatten.rb +40 -0
  107. data/lib/graphql/execution/instrumentation.rb +92 -0
  108. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  109. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  110. data/lib/graphql/execution/interpreter/arguments_cache.rb +103 -0
  111. data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
  112. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  113. data/lib/graphql/execution/interpreter/resolve.rb +70 -0
  114. data/lib/graphql/execution/interpreter/runtime.rb +949 -0
  115. data/lib/graphql/execution/interpreter.rb +122 -0
  116. data/lib/graphql/execution/lazy/lazy_method_map.rb +98 -0
  117. data/lib/graphql/execution/lazy/resolve.rb +91 -0
  118. data/lib/graphql/execution/lazy.rb +83 -0
  119. data/lib/graphql/execution/lookahead.rb +307 -0
  120. data/lib/graphql/execution/multiplex.rb +214 -0
  121. data/lib/graphql/execution/typecast.rb +50 -0
  122. data/lib/graphql/execution.rb +11 -0
  123. data/lib/graphql/execution_error.rb +58 -0
  124. data/lib/graphql/field/resolve.rb +59 -0
  125. data/lib/graphql/field.rb +226 -0
  126. data/lib/graphql/filter.rb +53 -0
  127. data/lib/graphql/float_type.rb +2 -0
  128. data/lib/graphql/function.rb +128 -0
  129. data/lib/graphql/id_type.rb +2 -0
  130. data/lib/graphql/input_object_type.rb +138 -0
  131. data/lib/graphql/int_type.rb +2 -0
  132. data/lib/graphql/integer_decoding_error.rb +17 -0
  133. data/lib/graphql/integer_encoding_error.rb +36 -0
  134. data/lib/graphql/interface_type.rb +72 -0
  135. data/lib/graphql/internal_representation/document.rb +27 -0
  136. data/lib/graphql/internal_representation/node.rb +206 -0
  137. data/lib/graphql/internal_representation/print.rb +51 -0
  138. data/lib/graphql/internal_representation/rewrite.rb +184 -0
  139. data/lib/graphql/internal_representation/scope.rb +88 -0
  140. data/lib/graphql/internal_representation/visit.rb +36 -0
  141. data/lib/graphql/internal_representation.rb +7 -0
  142. data/lib/graphql/introspection/base_object.rb +13 -0
  143. data/lib/graphql/introspection/directive_location_enum.rb +15 -0
  144. data/lib/graphql/introspection/directive_type.rb +29 -0
  145. data/lib/graphql/introspection/dynamic_fields.rb +17 -0
  146. data/lib/graphql/introspection/entry_points.rb +35 -0
  147. data/lib/graphql/introspection/enum_value_type.rb +23 -0
  148. data/lib/graphql/introspection/field_type.rb +28 -0
  149. data/lib/graphql/introspection/input_value_type.rb +67 -0
  150. data/lib/graphql/introspection/introspection_query.rb +7 -0
  151. data/lib/graphql/introspection/schema_type.rb +44 -0
  152. data/lib/graphql/introspection/type_kind_enum.rb +13 -0
  153. data/lib/graphql/introspection/type_type.rb +95 -0
  154. data/lib/graphql/introspection.rb +114 -0
  155. data/lib/graphql/invalid_name_error.rb +11 -0
  156. data/lib/graphql/invalid_null_error.rb +50 -0
  157. data/lib/graphql/language/block_string.rb +99 -0
  158. data/lib/graphql/language/cache.rb +37 -0
  159. data/lib/graphql/language/definition_slice.rb +41 -0
  160. data/lib/graphql/language/document_from_schema_definition.rb +347 -0
  161. data/lib/graphql/language/generation.rb +24 -0
  162. data/lib/graphql/language/lexer.rb +1467 -0
  163. data/lib/graphql/language/lexer.rl +258 -0
  164. data/lib/graphql/language/nodes.rb +707 -0
  165. data/lib/graphql/language/parser.rb +1974 -0
  166. data/lib/graphql/language/parser.y +544 -0
  167. data/lib/graphql/language/printer.rb +366 -0
  168. data/lib/graphql/language/sanitized_printer.rb +222 -0
  169. data/lib/graphql/language/token.rb +34 -0
  170. data/lib/graphql/language/visitor.rb +242 -0
  171. data/lib/graphql/language.rb +36 -0
  172. data/lib/graphql/list_type.rb +80 -0
  173. data/lib/graphql/load_application_object_failed_error.rb +22 -0
  174. data/lib/graphql/name_validator.rb +11 -0
  175. data/lib/graphql/non_null_type.rb +71 -0
  176. data/lib/graphql/object_type.rb +130 -0
  177. data/lib/graphql/pagination/active_record_relation_connection.rb +48 -0
  178. data/lib/graphql/pagination/array_connection.rb +77 -0
  179. data/lib/graphql/pagination/connection.rb +226 -0
  180. data/lib/graphql/pagination/connections.rb +160 -0
  181. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  182. data/lib/graphql/pagination/relation_connection.rb +196 -0
  183. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  184. data/lib/graphql/pagination.rb +6 -0
  185. data/lib/graphql/parse_error.rb +24 -0
  186. data/lib/graphql/query/arguments.rb +189 -0
  187. data/lib/graphql/query/arguments_cache.rb +24 -0
  188. data/lib/graphql/query/context.rb +371 -0
  189. data/lib/graphql/query/executor.rb +52 -0
  190. data/lib/graphql/query/fingerprint.rb +26 -0
  191. data/lib/graphql/query/input_validation_result.rb +43 -0
  192. data/lib/graphql/query/literal_input.rb +136 -0
  193. data/lib/graphql/query/null_context.rb +55 -0
  194. data/lib/graphql/query/result.rb +63 -0
  195. data/lib/graphql/query/serial_execution/field_resolution.rb +92 -0
  196. data/lib/graphql/query/serial_execution/operation_resolution.rb +19 -0
  197. data/lib/graphql/query/serial_execution/selection_resolution.rb +23 -0
  198. data/lib/graphql/query/serial_execution/value_resolution.rb +87 -0
  199. data/lib/graphql/query/serial_execution.rb +40 -0
  200. data/lib/graphql/query/validation_pipeline.rb +139 -0
  201. data/lib/graphql/query/variable_validation_error.rb +44 -0
  202. data/lib/graphql/query/variables.rb +78 -0
  203. data/lib/graphql/query.rb +454 -0
  204. data/lib/graphql/railtie.rb +117 -0
  205. data/lib/graphql/rake_task/validate.rb +63 -0
  206. data/lib/graphql/rake_task.rb +145 -0
  207. data/lib/graphql/relay/array_connection.rb +83 -0
  208. data/lib/graphql/relay/base_connection.rb +189 -0
  209. data/lib/graphql/relay/connection_instrumentation.rb +54 -0
  210. data/lib/graphql/relay/connection_resolve.rb +43 -0
  211. data/lib/graphql/relay/connection_type.rb +41 -0
  212. data/lib/graphql/relay/edge.rb +27 -0
  213. data/lib/graphql/relay/edge_type.rb +19 -0
  214. data/lib/graphql/relay/edges_instrumentation.rb +39 -0
  215. data/lib/graphql/relay/global_id_resolve.rb +18 -0
  216. data/lib/graphql/relay/mongo_relation_connection.rb +50 -0
  217. data/lib/graphql/relay/mutation/instrumentation.rb +23 -0
  218. data/lib/graphql/relay/mutation/resolve.rb +56 -0
  219. data/lib/graphql/relay/mutation/result.rb +38 -0
  220. data/lib/graphql/relay/mutation.rb +106 -0
  221. data/lib/graphql/relay/node.rb +39 -0
  222. data/lib/graphql/relay/page_info.rb +7 -0
  223. data/lib/graphql/relay/range_add.rb +59 -0
  224. data/lib/graphql/relay/relation_connection.rb +188 -0
  225. data/lib/graphql/relay/type_extensions.rb +32 -0
  226. data/lib/graphql/relay.rb +18 -0
  227. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  228. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  229. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  230. data/lib/graphql/rubocop.rb +4 -0
  231. data/lib/graphql/runtime_type_error.rb +5 -0
  232. data/lib/graphql/scalar_type.rb +91 -0
  233. data/lib/graphql/schema/addition.rb +247 -0
  234. data/lib/graphql/schema/argument.rb +383 -0
  235. data/lib/graphql/schema/base_64_bp.rb +26 -0
  236. data/lib/graphql/schema/base_64_encoder.rb +21 -0
  237. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +47 -0
  238. data/lib/graphql/schema/build_from_definition/resolve_map.rb +78 -0
  239. data/lib/graphql/schema/build_from_definition.rb +477 -0
  240. data/lib/graphql/schema/built_in_types.rb +12 -0
  241. data/lib/graphql/schema/catchall_middleware.rb +35 -0
  242. data/lib/graphql/schema/default_parse_error.rb +10 -0
  243. data/lib/graphql/schema/default_type_error.rb +17 -0
  244. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  245. data/lib/graphql/schema/directive/feature.rb +66 -0
  246. data/lib/graphql/schema/directive/flagged.rb +57 -0
  247. data/lib/graphql/schema/directive/include.rb +25 -0
  248. data/lib/graphql/schema/directive/skip.rb +25 -0
  249. data/lib/graphql/schema/directive/transform.rb +60 -0
  250. data/lib/graphql/schema/directive.rb +210 -0
  251. data/lib/graphql/schema/enum.rb +193 -0
  252. data/lib/graphql/schema/enum_value.rb +97 -0
  253. data/lib/graphql/schema/field/connection_extension.rb +76 -0
  254. data/lib/graphql/schema/field/scope_extension.rb +22 -0
  255. data/lib/graphql/schema/field.rb +880 -0
  256. data/lib/graphql/schema/field_extension.rb +69 -0
  257. data/lib/graphql/schema/find_inherited_value.rb +36 -0
  258. data/lib/graphql/schema/finder.rb +155 -0
  259. data/lib/graphql/schema/input_object.rb +253 -0
  260. data/lib/graphql/schema/interface.rb +136 -0
  261. data/lib/graphql/schema/introspection_system.rb +169 -0
  262. data/lib/graphql/schema/invalid_type_error.rb +7 -0
  263. data/lib/graphql/schema/late_bound_type.rb +33 -0
  264. data/lib/graphql/schema/list.rb +75 -0
  265. data/lib/graphql/schema/loader.rb +226 -0
  266. data/lib/graphql/schema/member/accepts_definition.rb +159 -0
  267. data/lib/graphql/schema/member/base_dsl_methods.rb +129 -0
  268. data/lib/graphql/schema/member/build_type.rb +180 -0
  269. data/lib/graphql/schema/member/cached_graphql_definition.rb +31 -0
  270. data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
  271. data/lib/graphql/schema/member/has_arguments.rb +332 -0
  272. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  273. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  274. data/lib/graphql/schema/member/has_directives.rb +98 -0
  275. data/lib/graphql/schema/member/has_fields.rb +163 -0
  276. data/lib/graphql/schema/member/has_interfaces.rb +90 -0
  277. data/lib/graphql/schema/member/has_path.rb +25 -0
  278. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  279. data/lib/graphql/schema/member/has_validators.rb +31 -0
  280. data/lib/graphql/schema/member/instrumentation.rb +131 -0
  281. data/lib/graphql/schema/member/relay_shortcuts.rb +47 -0
  282. data/lib/graphql/schema/member/scoped.rb +21 -0
  283. data/lib/graphql/schema/member/type_system_helpers.rb +38 -0
  284. data/lib/graphql/schema/member/validates_input.rb +33 -0
  285. data/lib/graphql/schema/member.rb +161 -0
  286. data/lib/graphql/schema/middleware_chain.rb +82 -0
  287. data/lib/graphql/schema/mutation.rb +94 -0
  288. data/lib/graphql/schema/non_null.rb +67 -0
  289. data/lib/graphql/schema/null_mask.rb +11 -0
  290. data/lib/graphql/schema/object.rb +150 -0
  291. data/lib/graphql/schema/possible_types.rb +44 -0
  292. data/lib/graphql/schema/printer.rb +100 -0
  293. data/lib/graphql/schema/relay_classic_mutation.rb +160 -0
  294. data/lib/graphql/schema/rescue_middleware.rb +60 -0
  295. data/lib/graphql/schema/resolver/has_payload_type.rb +96 -0
  296. data/lib/graphql/schema/resolver.rb +397 -0
  297. data/lib/graphql/schema/scalar.rb +69 -0
  298. data/lib/graphql/schema/subscription.rb +155 -0
  299. data/lib/graphql/schema/timeout.rb +123 -0
  300. data/lib/graphql/schema/timeout_middleware.rb +88 -0
  301. data/lib/graphql/schema/traversal.rb +228 -0
  302. data/lib/graphql/schema/type_expression.rb +43 -0
  303. data/lib/graphql/schema/type_membership.rb +48 -0
  304. data/lib/graphql/schema/union.rb +95 -0
  305. data/lib/graphql/schema/unique_within_type.rb +34 -0
  306. data/lib/graphql/schema/validation.rb +313 -0
  307. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  308. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  309. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  310. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  311. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  312. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  313. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  314. data/lib/graphql/schema/validator/required_validator.rb +68 -0
  315. data/lib/graphql/schema/validator.rb +174 -0
  316. data/lib/graphql/schema/warden.rb +409 -0
  317. data/lib/graphql/schema/wrapper.rb +29 -0
  318. data/lib/graphql/schema.rb +1945 -0
  319. data/lib/graphql/static_validation/all_rules.rb +40 -0
  320. data/lib/graphql/static_validation/base_visitor.rb +217 -0
  321. data/lib/graphql/static_validation/default_visitor.rb +15 -0
  322. data/lib/graphql/static_validation/definition_dependencies.rb +198 -0
  323. data/lib/graphql/static_validation/error.rb +46 -0
  324. data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
  325. data/lib/graphql/static_validation/literal_validator.rb +139 -0
  326. data/lib/graphql/static_validation/no_validate_visitor.rb +10 -0
  327. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +66 -0
  328. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +48 -0
  329. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +31 -0
  330. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
  331. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +71 -0
  332. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +37 -0
  333. data/lib/graphql/static_validation/rules/directives_are_defined.rb +23 -0
  334. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
  335. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +65 -0
  336. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
  337. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +30 -0
  338. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
  339. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +73 -0
  340. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
  341. data/lib/graphql/static_validation/rules/fields_will_merge.rb +418 -0
  342. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +53 -0
  343. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +30 -0
  344. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
  345. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +73 -0
  346. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
  347. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +39 -0
  348. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
  349. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +21 -0
  350. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
  351. data/lib/graphql/static_validation/rules/fragments_are_named.rb +16 -0
  352. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
  353. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +37 -0
  354. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
  355. data/lib/graphql/static_validation/rules/fragments_are_used.rb +32 -0
  356. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
  357. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  358. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  359. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +17 -0
  360. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
  361. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +41 -0
  362. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
  363. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +36 -0
  364. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
  365. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +37 -0
  366. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
  367. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +59 -0
  368. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
  369. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +17 -0
  370. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
  371. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +50 -0
  372. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
  373. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +46 -0
  374. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
  375. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +24 -0
  376. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
  377. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +153 -0
  378. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
  379. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +39 -0
  380. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
  381. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +155 -0
  382. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
  383. data/lib/graphql/static_validation/type_stack.rb +216 -0
  384. data/lib/graphql/static_validation/validation_context.rb +49 -0
  385. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  386. data/lib/graphql/static_validation/validator.rb +96 -0
  387. data/lib/graphql/static_validation.rb +19 -0
  388. data/lib/graphql/string_encoding_error.rb +20 -0
  389. data/lib/graphql/string_type.rb +2 -0
  390. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +245 -0
  391. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  392. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
  393. data/lib/graphql/subscriptions/event.rb +144 -0
  394. data/lib/graphql/subscriptions/instrumentation.rb +79 -0
  395. data/lib/graphql/subscriptions/serialize.rb +138 -0
  396. data/lib/graphql/subscriptions/subscription_root.rb +76 -0
  397. data/lib/graphql/subscriptions.rb +299 -0
  398. data/lib/graphql/tracing/active_support_notifications_tracing.rb +35 -0
  399. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  400. data/lib/graphql/tracing/appsignal_tracing.rb +51 -0
  401. data/lib/graphql/tracing/data_dog_tracing.rb +76 -0
  402. data/lib/graphql/tracing/new_relic_tracing.rb +51 -0
  403. data/lib/graphql/tracing/platform_tracing.rb +139 -0
  404. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +32 -0
  405. data/lib/graphql/tracing/prometheus_tracing.rb +67 -0
  406. data/lib/graphql/tracing/scout_tracing.rb +54 -0
  407. data/lib/graphql/tracing/skylight_tracing.rb +70 -0
  408. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  409. data/lib/graphql/tracing.rb +95 -0
  410. data/lib/graphql/type_kinds.rb +77 -0
  411. data/lib/graphql/types/big_int.rb +23 -0
  412. data/lib/graphql/types/boolean.rb +18 -0
  413. data/lib/graphql/types/float.rb +19 -0
  414. data/lib/graphql/types/id.rb +24 -0
  415. data/lib/graphql/types/int.rb +36 -0
  416. data/lib/graphql/types/iso_8601_date.rb +34 -0
  417. data/lib/graphql/types/iso_8601_date_time.rb +65 -0
  418. data/lib/graphql/types/json.rb +25 -0
  419. data/lib/graphql/types/relay/base_connection.rb +39 -0
  420. data/lib/graphql/types/relay/base_edge.rb +29 -0
  421. data/lib/graphql/types/relay/connection_behaviors.rb +156 -0
  422. data/lib/graphql/types/relay/default_relay.rb +27 -0
  423. data/lib/graphql/types/relay/edge_behaviors.rb +53 -0
  424. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  425. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  426. data/lib/graphql/types/relay/node.rb +15 -0
  427. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  428. data/lib/graphql/types/relay/node_field.rb +25 -0
  429. data/lib/graphql/types/relay/nodes_field.rb +27 -0
  430. data/lib/graphql/types/relay/page_info.rb +11 -0
  431. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  432. data/lib/graphql/types/relay.rb +41 -0
  433. data/lib/graphql/types/string.rb +29 -0
  434. data/lib/graphql/types.rb +11 -0
  435. data/lib/graphql/unauthorized_error.rb +29 -0
  436. data/lib/graphql/unauthorized_field_error.rb +23 -0
  437. data/lib/graphql/union_type.rb +115 -0
  438. data/lib/graphql/unresolved_type_error.rb +35 -0
  439. data/lib/graphql/upgrader/member.rb +937 -0
  440. data/lib/graphql/upgrader/schema.rb +38 -0
  441. data/lib/graphql/version.rb +4 -0
  442. data/lib/graphql.rb +168 -0
  443. data/readme.md +49 -0
  444. metadata +714 -0
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+ require "set"
3
+ module GraphQL
4
+ class Subscriptions
5
+ # Serialization helpers for passing subscription data around.
6
+ # @api private
7
+ module Serialize
8
+ GLOBALID_KEY = "__gid__"
9
+ SYMBOL_KEY = "__sym__"
10
+ SYMBOL_KEYS_KEY = "__sym_keys__"
11
+ TIMESTAMP_KEY = "__timestamp__"
12
+ TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S.%N%z" # eg '2020-01-01 23:59:59.123456789+05:00'
13
+ OPEN_STRUCT_KEY = "__ostruct__"
14
+
15
+ module_function
16
+
17
+ # @param str [String] A serialized object from {.dump}
18
+ # @return [Object] An object equivalent to the one passed to {.dump}
19
+ def load(str)
20
+ parsed_obj = JSON.parse(str)
21
+ load_value(parsed_obj)
22
+ end
23
+
24
+ # @param obj [Object] Some subscription-related data to dump
25
+ # @return [String] The stringified object
26
+ def dump(obj)
27
+ JSON.generate(dump_value(obj), quirks_mode: true)
28
+ end
29
+
30
+ # This is for turning objects into subscription scopes.
31
+ # It's a one-way transformation, can't reload this :'(
32
+ # @param obj [Object]
33
+ # @return [String]
34
+ def dump_recursive(obj)
35
+ case
36
+ when obj.is_a?(Array)
37
+ obj.map { |i| dump_recursive(i) }.join(':')
38
+ when obj.is_a?(Hash)
39
+ obj.map { |k, v| "#{dump_recursive(k)}:#{dump_recursive(v)}" }.join(":")
40
+ when obj.is_a?(GraphQL::Schema::InputObject)
41
+ dump_recursive(obj.to_h)
42
+ when obj.respond_to?(:to_gid_param)
43
+ obj.to_gid_param
44
+ when obj.respond_to?(:to_param)
45
+ obj.to_param
46
+ else
47
+ obj.to_s
48
+ end
49
+ end
50
+
51
+ class << self
52
+ private
53
+
54
+ # @param value [Object] A parsed JSON object
55
+ # @return [Object] An object that load Global::Identification recursive
56
+ def load_value(value)
57
+ if value.is_a?(Array)
58
+ is_gids = (v1 = value[0]).is_a?(Hash) && v1.size == 1 && v1[GLOBALID_KEY]
59
+ if is_gids
60
+ # Assume it's an array of global IDs
61
+ ids = value.map { |v| v[GLOBALID_KEY] }
62
+ GlobalID::Locator.locate_many(ids)
63
+ else
64
+ value.map { |item| load_value(item) }
65
+ end
66
+ elsif value.is_a?(Hash)
67
+ if value.size == 1
68
+ case value.keys.first # there's only 1 key
69
+ when GLOBALID_KEY
70
+ GlobalID::Locator.locate(value[GLOBALID_KEY])
71
+ when SYMBOL_KEY
72
+ value[SYMBOL_KEY].to_sym
73
+ when TIMESTAMP_KEY
74
+ timestamp_class_name, timestamp_s = value[TIMESTAMP_KEY]
75
+ timestamp_class = Object.const_get(timestamp_class_name)
76
+ timestamp_class.strptime(timestamp_s, TIMESTAMP_FORMAT)
77
+ when OPEN_STRUCT_KEY
78
+ ostruct_values = load_value(value[OPEN_STRUCT_KEY])
79
+ OpenStruct.new(ostruct_values)
80
+ else
81
+ key = value.keys.first
82
+ { key => load_value(value[key]) }
83
+ end
84
+ else
85
+ loaded_h = {}
86
+ sym_keys = value.fetch(SYMBOL_KEYS_KEY, [])
87
+ value.each do |k, v|
88
+ if k == SYMBOL_KEYS_KEY
89
+ next
90
+ end
91
+ if sym_keys.include?(k)
92
+ k = k.to_sym
93
+ end
94
+ loaded_h[k] = load_value(v)
95
+ end
96
+ loaded_h
97
+ end
98
+ else
99
+ value
100
+ end
101
+ end
102
+
103
+ # @param obj [Object] Some subscription-related data to dump
104
+ # @return [Object] The object that converted Global::Identification
105
+ def dump_value(obj)
106
+ if obj.is_a?(Array)
107
+ obj.map{|item| dump_value(item)}
108
+ elsif obj.is_a?(Hash)
109
+ symbol_keys = nil
110
+ dumped_h = {}
111
+ obj.each do |k, v|
112
+ dumped_h[k.to_s] = dump_value(v)
113
+ if k.is_a?(Symbol)
114
+ symbol_keys ||= Set.new
115
+ symbol_keys << k.to_s
116
+ end
117
+ end
118
+ if symbol_keys
119
+ dumped_h[SYMBOL_KEYS_KEY] = symbol_keys.to_a
120
+ end
121
+ dumped_h
122
+ elsif obj.is_a?(Symbol)
123
+ { SYMBOL_KEY => obj.to_s }
124
+ elsif obj.respond_to?(:to_gid_param)
125
+ {GLOBALID_KEY => obj.to_gid_param}
126
+ elsif obj.is_a?(Date) || obj.is_a?(Time)
127
+ # DateTime extends Date; for TimeWithZone, call `.utc` first.
128
+ { TIMESTAMP_KEY => [obj.class.name, obj.strftime(TIMESTAMP_FORMAT)] }
129
+ elsif obj.is_a?(OpenStruct)
130
+ { OPEN_STRUCT_KEY => dump_value(obj.to_h) }
131
+ else
132
+ obj
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Subscriptions
5
+ # @api private
6
+ # @deprecated This module is no longer needed.
7
+ module SubscriptionRoot
8
+ def self.extended(child_cls)
9
+ GraphQL::Deprecation.warn "`extend GraphQL::Subscriptions::SubscriptionRoot` is no longer required; you can remove it from your Subscription type (#{child_cls})"
10
+ child_cls.include(InstanceMethods)
11
+ end
12
+
13
+ # This is for maintaining backwards compatibility:
14
+ # if a subscription field is created without a `subscription:` resolver class,
15
+ # then implement the method with the previous default behavior.
16
+ module InstanceMethods
17
+ def skip_subscription_root(*)
18
+ if context.query.subscription_update?
19
+ object
20
+ else
21
+ context.skip
22
+ end
23
+ end
24
+ end
25
+
26
+ def field(*args, extensions: [], **rest, &block)
27
+ extensions += [Extension]
28
+ # Backwards-compat for schemas
29
+ if !rest[:subscription]
30
+ name = args.first
31
+ alias_method(name, :skip_subscription_root)
32
+ end
33
+ super(*args, extensions: extensions, **rest, &block)
34
+ end
35
+
36
+ class Extension < GraphQL::Schema::FieldExtension
37
+ def after_resolve(value:, context:, object:, arguments:, **rest)
38
+ if value.is_a?(GraphQL::ExecutionError)
39
+ value
40
+ elsif (events = context.namespace(:subscriptions)[:events])
41
+ # This is the first execution, so gather an Event
42
+ # for the backend to register:
43
+ event = Subscriptions::Event.new(
44
+ name: field.name,
45
+ arguments: arguments_without_field_extras(arguments: arguments),
46
+ context: context,
47
+ field: field,
48
+ )
49
+ events << event
50
+ value
51
+ elsif context.query.subscription_topic == Subscriptions::Event.serialize(
52
+ field.name,
53
+ arguments_without_field_extras(arguments: arguments),
54
+ field,
55
+ scope: (field.subscription_scope ? context[field.subscription_scope] : nil),
56
+ )
57
+ # This is a subscription update. The resolver returned `skip` if it should be skipped,
58
+ # or else it returned an object to resolve the update.
59
+ value
60
+ else
61
+ # This is a subscription update, but this event wasn't triggered.
62
+ context.skip
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def arguments_without_field_extras(arguments:)
69
+ arguments.dup.tap do |event_args|
70
+ field.extras.each { |k| event_args.delete(k) }
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,299 @@
1
+ # frozen_string_literal: true
2
+ require "securerandom"
3
+ require "graphql/subscriptions/broadcast_analyzer"
4
+ require "graphql/subscriptions/event"
5
+ require "graphql/subscriptions/instrumentation"
6
+ require "graphql/subscriptions/serialize"
7
+ require "graphql/subscriptions/action_cable_subscriptions"
8
+ require "graphql/subscriptions/subscription_root"
9
+ require "graphql/subscriptions/default_subscription_resolve_extension"
10
+
11
+ module GraphQL
12
+ class Subscriptions
13
+ # Raised when either:
14
+ # - the triggered `event_name` doesn't match a field in the schema; or
15
+ # - one or more arguments don't match the field arguments
16
+ class InvalidTriggerError < GraphQL::Error
17
+ end
18
+
19
+ # Raised when either:
20
+ # - An initial subscription didn't have a value for `context[subscription_scope]`
21
+ # - Or, an update didn't pass `.trigger(..., scope:)`
22
+ # When raised, the initial subscription or update fails completely.
23
+ class SubscriptionScopeMissingError < GraphQL::Error
24
+ end
25
+
26
+ # @see {Subscriptions#initialize} for options, concrete implementations may add options.
27
+ def self.use(defn, options = {})
28
+ schema = defn.is_a?(Class) ? defn : defn.target
29
+
30
+ if schema.subscriptions
31
+ raise ArgumentError, "Can't reinstall subscriptions. #{schema} is using #{schema.subscriptions}, can't also add #{self}"
32
+ end
33
+
34
+ instrumentation = Subscriptions::Instrumentation.new(schema: schema)
35
+ defn.instrument(:query, instrumentation)
36
+ if !schema.is_a?(Class)
37
+ defn.instrument(:field, instrumentation)
38
+ end
39
+ options[:schema] = schema
40
+ schema.subscriptions = self.new(**options)
41
+ schema.add_subscription_extension_if_necessary
42
+ nil
43
+ end
44
+
45
+ # @param schema [Class] the GraphQL schema this manager belongs to
46
+ def initialize(schema:, broadcast: false, default_broadcastable: false, **rest)
47
+ if broadcast
48
+ if !schema.using_ast_analysis?
49
+ raise ArgumentError, "`broadcast: true` requires AST analysis, add `using GraphQL::Analysis::AST` to your schema or see https://graphql-ruby.org/queries/ast_analysis.html."
50
+ end
51
+ schema.query_analyzer(Subscriptions::BroadcastAnalyzer)
52
+ end
53
+ @default_broadcastable = default_broadcastable
54
+ @schema = schema
55
+ end
56
+
57
+ # @return [Boolean] Used when fields don't have `broadcastable:` explicitly set
58
+ attr_reader :default_broadcastable
59
+
60
+ # Fetch subscriptions matching this field + arguments pair
61
+ # And pass them off to the queue.
62
+ # @param event_name [String]
63
+ # @param args [Hash<String, Symbol => Object]
64
+ # @param object [Object]
65
+ # @param scope [Symbol, String]
66
+ # @return [void]
67
+ def trigger(event_name, args, object, scope: nil)
68
+ event_name = event_name.to_s
69
+
70
+ # Try with the verbatim input first:
71
+ field = @schema.get_field(@schema.subscription, event_name)
72
+
73
+ if field.nil?
74
+ # And if it wasn't found, normalize it:
75
+ normalized_event_name = normalize_name(event_name)
76
+ field = @schema.get_field(@schema.subscription, normalized_event_name)
77
+ if field.nil?
78
+ raise InvalidTriggerError, "No subscription matching trigger: #{event_name} (looked for #{@schema.subscription.graphql_name}.#{normalized_event_name})"
79
+ end
80
+ else
81
+ # Since we found a field, the original input was already normalized
82
+ normalized_event_name = event_name
83
+ end
84
+
85
+ # Normalize symbol-keyed args to strings, try camelizing them
86
+ # Should this accept a real context somehow?
87
+ normalized_args = normalize_arguments(normalized_event_name, field, args, GraphQL::Query::NullContext)
88
+
89
+ event = Subscriptions::Event.new(
90
+ name: normalized_event_name,
91
+ arguments: normalized_args,
92
+ field: field,
93
+ scope: scope,
94
+ )
95
+ execute_all(event, object)
96
+ end
97
+
98
+ # `event` was triggered on `object`, and `subscription_id` was subscribed,
99
+ # so it should be updated.
100
+ #
101
+ # Load `subscription_id`'s GraphQL data, re-evaluate the query and return the result.
102
+ #
103
+ # @param subscription_id [String]
104
+ # @param event [GraphQL::Subscriptions::Event] The event which was triggered
105
+ # @param object [Object] The value for the subscription field
106
+ # @return [GraphQL::Query::Result]
107
+ def execute_update(subscription_id, event, object)
108
+ # Lookup the saved data for this subscription
109
+ query_data = read_subscription(subscription_id)
110
+ if query_data.nil?
111
+ delete_subscription(subscription_id)
112
+ return nil
113
+ end
114
+
115
+ # Fetch the required keys from the saved data
116
+ query_string = query_data.fetch(:query_string)
117
+ variables = query_data.fetch(:variables)
118
+ context = query_data.fetch(:context)
119
+ operation_name = query_data.fetch(:operation_name)
120
+ result = @schema.execute(
121
+ query: query_string,
122
+ context: context,
123
+ subscription_topic: event.topic,
124
+ operation_name: operation_name,
125
+ variables: variables,
126
+ root_value: object,
127
+ )
128
+ subscriptions_context = result.context.namespace(:subscriptions)
129
+ if subscriptions_context[:no_update]
130
+ result = nil
131
+ end
132
+
133
+ unsubscribed = subscriptions_context[:unsubscribed]
134
+
135
+ if unsubscribed
136
+ # `unsubscribe` was called, clean up on our side
137
+ # TODO also send `{more: false}` to client?
138
+ delete_subscription(subscription_id)
139
+ result = nil
140
+ end
141
+
142
+ result
143
+ end
144
+
145
+ # Run the update query for this subscription and deliver it
146
+ # @see {#execute_update}
147
+ # @see {#deliver}
148
+ # @return [void]
149
+ def execute(subscription_id, event, object)
150
+ res = execute_update(subscription_id, event, object)
151
+ if !res.nil?
152
+ deliver(subscription_id, res)
153
+ end
154
+ end
155
+
156
+ # Event `event` occurred on `object`,
157
+ # Update all subscribers.
158
+ # @param event [Subscriptions::Event]
159
+ # @param object [Object]
160
+ # @return [void]
161
+ def execute_all(event, object)
162
+ raise GraphQL::RequiredImplementationMissingError
163
+ end
164
+
165
+ # The system wants to send an update to this subscription.
166
+ # Read its data and return it.
167
+ # @param subscription_id [String]
168
+ # @return [Hash] Containing required keys
169
+ def read_subscription(subscription_id)
170
+ raise GraphQL::RequiredImplementationMissingError
171
+ end
172
+
173
+ # A subscription query was re-evaluated, returning `result`.
174
+ # The result should be send to `subscription_id`.
175
+ # @param subscription_id [String]
176
+ # @param result [Hash]
177
+ # @return [void]
178
+ def deliver(subscription_id, result)
179
+ raise GraphQL::RequiredImplementationMissingError
180
+ end
181
+
182
+ # `query` was executed and found subscriptions to `events`.
183
+ # Update the database to reflect this new state.
184
+ # @param query [GraphQL::Query]
185
+ # @param events [Array<GraphQL::Subscriptions::Event>]
186
+ # @return [void]
187
+ def write_subscription(query, events)
188
+ raise GraphQL::RequiredImplementationMissingError
189
+ end
190
+
191
+ # A subscription was terminated server-side.
192
+ # Clean up the database.
193
+ # @param subscription_id [String]
194
+ # @return void.
195
+ def delete_subscription(subscription_id)
196
+ raise GraphQL::RequiredImplementationMissingError
197
+ end
198
+
199
+ # @return [String] A new unique identifier for a subscription
200
+ def build_id
201
+ SecureRandom.uuid
202
+ end
203
+
204
+ # Convert a user-provided event name or argument
205
+ # to the equivalent in GraphQL.
206
+ #
207
+ # By default, it converts the identifier to camelcase.
208
+ # Override this in a subclass to change the transformation.
209
+ #
210
+ # @param event_or_arg_name [String, Symbol]
211
+ # @return [String]
212
+ def normalize_name(event_or_arg_name)
213
+ Schema::Member::BuildType.camelize(event_or_arg_name.to_s)
214
+ end
215
+
216
+ # @return [Boolean] if true, then a query like this one would be broadcasted
217
+ def broadcastable?(query_str, **query_options)
218
+ query = GraphQL::Query.new(@schema, query_str, **query_options)
219
+ if !query.valid?
220
+ raise "Invalid query: #{query.validation_errors.map(&:to_h).inspect}"
221
+ end
222
+ GraphQL::Analysis::AST.analyze_query(query, @schema.query_analyzers)
223
+ query.context.namespace(:subscriptions)[:subscription_broadcastable]
224
+ end
225
+
226
+ private
227
+
228
+ # Recursively normalize `args` as belonging to `arg_owner`:
229
+ # - convert symbols to strings,
230
+ # - if needed, camelize the string (using {#normalize_name})
231
+ # @param arg_owner [GraphQL::Field, GraphQL::BaseType]
232
+ # @param args [Hash, Array, Any] some GraphQL input value to coerce as `arg_owner`
233
+ # @return [Any] normalized arguments value
234
+ def normalize_arguments(event_name, arg_owner, args, context)
235
+ case arg_owner
236
+ when GraphQL::Field, GraphQL::InputObjectType, GraphQL::Schema::Field, Class
237
+ if arg_owner.is_a?(Class) && !arg_owner.kind.input_object?
238
+ # it's a type, but not an input object
239
+ return args
240
+ end
241
+ normalized_args = {}
242
+ missing_arg_names = []
243
+ args.each do |k, v|
244
+ arg_name = k.to_s
245
+ arg_defn = arg_owner.get_argument(arg_name, context)
246
+ if arg_defn
247
+ normalized_arg_name = arg_name
248
+ else
249
+ normalized_arg_name = normalize_name(arg_name)
250
+ arg_defn = arg_owner.get_argument(normalized_arg_name, context)
251
+ end
252
+
253
+ if arg_defn
254
+ if arg_defn.loads
255
+ normalized_arg_name = arg_defn.keyword.to_s
256
+ end
257
+ normalized = normalize_arguments(event_name, arg_defn.type, v, context)
258
+ normalized_args[normalized_arg_name] = normalized
259
+ else
260
+ # Couldn't find a matching argument definition
261
+ missing_arg_names << arg_name
262
+ end
263
+ end
264
+
265
+ # Backfill default values so that trigger arguments
266
+ # match query arguments.
267
+ arg_owner.arguments(context).each do |_name, arg_defn|
268
+ if arg_defn.default_value? && !normalized_args.key?(arg_defn.name)
269
+ default_value = arg_defn.default_value
270
+ # We don't have an underlying "object" here, so it can't call methods.
271
+ # This is broken.
272
+ normalized_args[arg_defn.name] = arg_defn.prepare_value(nil, default_value, context: context)
273
+ end
274
+ end
275
+
276
+ if missing_arg_names.any?
277
+ arg_owner_name = if arg_owner.is_a?(GraphQL::Field)
278
+ "Subscription.#{arg_owner.name}"
279
+ elsif arg_owner.is_a?(GraphQL::Schema::Field)
280
+ arg_owner.path
281
+ elsif arg_owner.is_a?(Class)
282
+ arg_owner.graphql_name
283
+ else
284
+ arg_owner.to_s
285
+ end
286
+ raise InvalidTriggerError, "Can't trigger Subscription.#{event_name}, received undefined arguments: #{missing_arg_names.join(", ")}. (Should match arguments of #{arg_owner_name}.)"
287
+ end
288
+
289
+ normalized_args
290
+ when GraphQL::ListType, GraphQL::Schema::List
291
+ args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
292
+ when GraphQL::NonNullType, GraphQL::Schema::NonNull
293
+ normalize_arguments(event_name, arg_owner.of_type, args, context)
294
+ else
295
+ args
296
+ end
297
+ end
298
+ end
299
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Tracing
5
+ # This implementation forwards events to ActiveSupport::Notifications
6
+ # with a `graphql` suffix.
7
+ #
8
+ # @see KEYS for event names
9
+ module ActiveSupportNotificationsTracing
10
+ # A cache of frequently-used keys to avoid needless string allocations
11
+ KEYS = {
12
+ "lex" => "lex.graphql",
13
+ "parse" => "parse.graphql",
14
+ "validate" => "validate.graphql",
15
+ "analyze_multiplex" => "analyze_multiplex.graphql",
16
+ "analyze_query" => "analyze_query.graphql",
17
+ "execute_query" => "execute_query.graphql",
18
+ "execute_query_lazy" => "execute_query_lazy.graphql",
19
+ "execute_field" => "execute_field.graphql",
20
+ "execute_field_lazy" => "execute_field_lazy.graphql",
21
+ "authorized" => "authorized.graphql",
22
+ "authorized_lazy" => "authorized_lazy.graphql",
23
+ "resolve_type" => "resolve_type.graphql",
24
+ "resolve_type_lazy" => "resolve_type.graphql",
25
+ }
26
+
27
+ def self.trace(key, metadata)
28
+ prefixed_key = KEYS[key] || "#{key}.graphql"
29
+ ActiveSupport::Notifications.instrument(prefixed_key, metadata) do
30
+ yield
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end