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,397 @@
1
+ # frozen_string_literal: true
2
+ require "graphql/schema/resolver/has_payload_type"
3
+
4
+ module GraphQL
5
+ class Schema
6
+ # A class-based container for field configuration and resolution logic. It supports:
7
+ #
8
+ # - Arguments, via `.argument(...)` helper, which will be applied to the field.
9
+ # - Return type, via `.type(..., null: ...)`, which will be applied to the field.
10
+ # - Description, via `.description(...)`, which will be applied to the field
11
+ # - Resolution, via `#resolve(**args)` method, which will be called to resolve the field.
12
+ # - `#object` and `#context` accessors for use during `#resolve`.
13
+ #
14
+ # Resolvers can be attached with the `resolver:` option in a `field(...)` call.
15
+ #
16
+ # A resolver's configuration may be overridden with other keywords in the `field(...)` call.
17
+ #
18
+ # See the {.field_options} to see how a Resolver becomes a set of field configuration options.
19
+ #
20
+ # @see {GraphQL::Schema::Mutation} for a concrete subclass of `Resolver`.
21
+ # @see {GraphQL::Function} `Resolver` is a replacement for `GraphQL::Function`
22
+ class Resolver
23
+ include Schema::Member::GraphQLTypeNames
24
+ # Really we only need description from here, but:
25
+ extend Schema::Member::BaseDSLMethods
26
+ extend GraphQL::Schema::Member::HasArguments
27
+ extend GraphQL::Schema::Member::HasValidators
28
+ include Schema::Member::HasPath
29
+ extend Schema::Member::HasPath
30
+
31
+ # @param object [Object] The application object that this field is being resolved on
32
+ # @param context [GraphQL::Query::Context]
33
+ # @param field [GraphQL::Schema::Field]
34
+ def initialize(object:, context:, field:)
35
+ @object = object
36
+ @context = context
37
+ @field = field
38
+ # Since this hash is constantly rebuilt, cache it for this call
39
+ @arguments_by_keyword = {}
40
+ self.class.arguments(context).each do |name, arg|
41
+ @arguments_by_keyword[arg.keyword] = arg
42
+ end
43
+ @prepared_arguments = nil
44
+ end
45
+
46
+ # @return [Object] The application object this field is being resolved on
47
+ attr_reader :object
48
+
49
+ # @return [GraphQL::Query::Context]
50
+ attr_reader :context
51
+
52
+ # @return [GraphQL::Dataloader]
53
+ def dataloader
54
+ context.dataloader
55
+ end
56
+
57
+ # @return [GraphQL::Schema::Field]
58
+ attr_reader :field
59
+
60
+ def arguments
61
+ @prepared_arguments || raise("Arguments have not been prepared yet, still waiting for #load_arguments to resolve. (Call `.arguments` later in the code.)")
62
+ end
63
+
64
+ # This method is _actually_ called by the runtime,
65
+ # it does some preparation and then eventually calls
66
+ # the user-defined `#resolve` method.
67
+ # @api private
68
+ def resolve_with_support(**args)
69
+ # First call the ready? hook which may raise
70
+ ready_val = if args.any?
71
+ ready?(**args)
72
+ else
73
+ ready?
74
+ end
75
+ context.schema.after_lazy(ready_val) do |is_ready, ready_early_return|
76
+ if ready_early_return
77
+ if is_ready != false
78
+ raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{authorized_result.inspect}, #{ready_early_return.inspect}]"
79
+ else
80
+ ready_early_return
81
+ end
82
+ elsif is_ready
83
+ # Then call each prepare hook, which may return a different value
84
+ # for that argument, or may return a lazy object
85
+ load_arguments_val = load_arguments(args)
86
+ context.schema.after_lazy(load_arguments_val) do |loaded_args|
87
+ @prepared_arguments = loaded_args
88
+ Schema::Validator.validate!(self.class.validators, object, context, loaded_args, as: @field)
89
+ # Then call `authorized?`, which may raise or may return a lazy object
90
+ authorized_val = if loaded_args.any?
91
+ authorized?(**loaded_args)
92
+ else
93
+ authorized?
94
+ end
95
+ context.schema.after_lazy(authorized_val) do |(authorized_result, early_return)|
96
+ # If the `authorized?` returned two values, `false, early_return`,
97
+ # then use the early return value instead of continuing
98
+ if early_return
99
+ if authorized_result == false
100
+ early_return
101
+ else
102
+ raise "Unexpected result from #authorized? (expected `true`, `false` or `[false, {...}]`): [#{authorized_result.inspect}, #{early_return.inspect}]"
103
+ end
104
+ elsif authorized_result
105
+ # Finally, all the hooks have passed, so resolve it
106
+ if loaded_args.any?
107
+ public_send(self.class.resolve_method, **loaded_args)
108
+ else
109
+ public_send(self.class.resolve_method)
110
+ end
111
+ else
112
+ raise GraphQL::UnauthorizedFieldError.new(context: context, object: object, type: field.owner, field: field)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ # Do the work. Everything happens here.
121
+ # @return [Object] An object corresponding to the return type
122
+ def resolve(**args)
123
+ raise GraphQL::RequiredImplementationMissingError, "#{self.class.name}#resolve should execute the field's logic"
124
+ end
125
+
126
+ # Called before arguments are prepared.
127
+ # Implement this hook to make checks before doing any work.
128
+ #
129
+ # If it returns a lazy object (like a promise), it will be synced by GraphQL
130
+ # (but the resulting value won't be used).
131
+ #
132
+ # @param args [Hash] The input arguments, if there are any
133
+ # @raise [GraphQL::ExecutionError] To add an error to the response
134
+ # @raise [GraphQL::UnauthorizedError] To signal an authorization failure
135
+ # @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
136
+ def ready?(**args)
137
+ true
138
+ end
139
+
140
+ # Called after arguments are loaded, but before resolving.
141
+ #
142
+ # Override it to check everything before calling the mutation.
143
+ # @param inputs [Hash] The input arguments
144
+ # @raise [GraphQL::ExecutionError] To add an error to the response
145
+ # @raise [GraphQL::UnauthorizedError] To signal an authorization failure
146
+ # @return [Boolean, early_return_data] If `false`, execution will stop (and `early_return_data` will be returned instead, if present.)
147
+ def authorized?(**inputs)
148
+ self.class.arguments(context).each_value do |argument|
149
+ arg_keyword = argument.keyword
150
+ if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value)
151
+ arg_auth, err = argument.authorized?(self, arg_value, context)
152
+ if !arg_auth
153
+ return arg_auth, err
154
+ else
155
+ true
156
+ end
157
+ else
158
+ true
159
+ end
160
+ end
161
+ end
162
+
163
+ # Called when an object loaded by `loads:` fails the `.authorized?` check for its resolved GraphQL object type.
164
+ #
165
+ # By default, the error is re-raised and passed along to {{Schema.unauthorized_object}}.
166
+ #
167
+ # Any value returned here will be used _instead of_ of the loaded object.
168
+ # @param err [GraphQL::UnauthorizedError]
169
+ def unauthorized_object(err)
170
+ raise err
171
+ end
172
+
173
+ private
174
+
175
+ def load_arguments(args)
176
+ prepared_args = {}
177
+ prepare_lazies = []
178
+
179
+ args.each do |key, value|
180
+ arg_defn = @arguments_by_keyword[key]
181
+ if arg_defn
182
+ prepped_value = prepared_args[key] = arg_defn.load_and_authorize_value(self, value, context)
183
+ if context.schema.lazy?(prepped_value)
184
+ prepare_lazies << context.schema.after_lazy(prepped_value) do |finished_prepped_value|
185
+ prepared_args[key] = finished_prepped_value
186
+ end
187
+ end
188
+ else
189
+ # these are `extras:`
190
+ prepared_args[key] = value
191
+ end
192
+ end
193
+
194
+ # Avoid returning a lazy if none are needed
195
+ if prepare_lazies.any?
196
+ GraphQL::Execution::Lazy.all(prepare_lazies).then { prepared_args }
197
+ else
198
+ prepared_args
199
+ end
200
+ end
201
+
202
+ def get_argument(name, context = GraphQL::Query::NullContext)
203
+ self.class.get_argument(name, context)
204
+ end
205
+
206
+ class << self
207
+ # Default `:resolve` set below.
208
+ # @return [Symbol] The method to call on instances of this object to resolve the field
209
+ def resolve_method(new_method = nil)
210
+ if new_method
211
+ @resolve_method = new_method
212
+ end
213
+ @resolve_method || (superclass.respond_to?(:resolve_method) ? superclass.resolve_method : :resolve)
214
+ end
215
+
216
+ # Additional info injected into {#resolve}
217
+ # @see {GraphQL::Schema::Field#extras}
218
+ def extras(new_extras = nil)
219
+ if new_extras
220
+ @own_extras = new_extras
221
+ end
222
+ own_extras = @own_extras || []
223
+ own_extras + (superclass.respond_to?(:extras) ? superclass.extras : [])
224
+ end
225
+
226
+ # If `true` (default), then the return type for this resolver will be nullable.
227
+ # If `false`, then the return type is non-null.
228
+ #
229
+ # @see #type which sets the return type of this field and accepts a `null:` option
230
+ # @param allow_null [Boolean] Whether or not the response can be null
231
+ def null(allow_null = nil)
232
+ if !allow_null.nil?
233
+ @null = allow_null
234
+ end
235
+
236
+ @null.nil? ? (superclass.respond_to?(:null) ? superclass.null : true) : @null
237
+ end
238
+
239
+ # Call this method to get the return type of the field,
240
+ # or use it as a configuration method to assign a return type
241
+ # instead of generating one.
242
+ # TODO unify with {#null}
243
+ # @param new_type [Class, Array<Class>, nil] If a type definition class is provided, it will be used as the return type of the field
244
+ # @param null [true, false] Whether or not the field may return `nil`
245
+ # @return [Class] The type which this field returns.
246
+ def type(new_type = nil, null: nil)
247
+ if new_type
248
+ if null.nil?
249
+ raise ArgumentError, "required argument `null:` is missing"
250
+ end
251
+ @type_expr = new_type
252
+ @null = null
253
+ else
254
+ if @type_expr
255
+ GraphQL::Schema::Member::BuildType.parse_type(@type_expr, null: @null)
256
+ elsif superclass.respond_to?(:type)
257
+ superclass.type
258
+ else
259
+ nil
260
+ end
261
+ end
262
+ end
263
+
264
+ # Specifies the complexity of the field. Defaults to `1`
265
+ # @return [Integer, Proc]
266
+ def complexity(new_complexity = nil)
267
+ if new_complexity
268
+ @complexity = new_complexity
269
+ end
270
+ @complexity || (superclass.respond_to?(:complexity) ? superclass.complexity : 1)
271
+ end
272
+
273
+ def broadcastable(new_broadcastable)
274
+ @broadcastable = new_broadcastable
275
+ end
276
+
277
+ # @return [Boolean, nil]
278
+ def broadcastable?
279
+ if defined?(@broadcastable)
280
+ @broadcastable
281
+ else
282
+ (superclass.respond_to?(:broadcastable?) ? superclass.broadcastable? : nil)
283
+ end
284
+ end
285
+
286
+ # Get or set the `max_page_size:` which will be configured for fields using this resolver
287
+ # (`nil` means "unlimited max page size".)
288
+ # @param max_page_size [Integer, nil] Set a new value
289
+ # @return [Integer, nil] The `max_page_size` assigned to fields that use this resolver
290
+ def max_page_size(new_max_page_size = :not_given)
291
+ if new_max_page_size != :not_given
292
+ @max_page_size = new_max_page_size
293
+ elsif defined?(@max_page_size)
294
+ @max_page_size
295
+ elsif superclass.respond_to?(:max_page_size)
296
+ superclass.max_page_size
297
+ else
298
+ nil
299
+ end
300
+ end
301
+
302
+ # @return [Boolean] `true` if this resolver or a superclass has an assigned `max_page_size`
303
+ def has_max_page_size?
304
+ defined?(@max_page_size) || (superclass.respond_to?(:has_max_page_size?) && superclass.has_max_page_size?)
305
+ end
306
+
307
+ def field_options
308
+
309
+ all_args = {}
310
+ all_argument_definitions.each do |arg|
311
+ if (prev_entry = all_args[arg.graphql_name])
312
+ if prev_entry.is_a?(Array)
313
+ prev_entry << arg
314
+ else
315
+ all_args[arg.graphql_name] = [prev_entry, arg]
316
+ end
317
+ else
318
+ all_args[arg.graphql_name] = arg
319
+ end
320
+ end
321
+
322
+ field_opts = {
323
+ type: type_expr,
324
+ description: description,
325
+ extras: extras,
326
+ resolver_method: :resolve_with_support,
327
+ resolver_class: self,
328
+ arguments: all_args,
329
+ null: null,
330
+ complexity: complexity,
331
+ broadcastable: broadcastable?,
332
+ }
333
+
334
+ # If there aren't any, then the returned array is `[].freeze`,
335
+ # but passing that along breaks some user code.
336
+ if (exts = extensions).any?
337
+ field_opts[:extensions] = exts
338
+ end
339
+
340
+ if has_max_page_size?
341
+ field_opts[:max_page_size] = max_page_size
342
+ end
343
+
344
+ field_opts
345
+ end
346
+
347
+ # A non-normalized type configuration, without `null` applied
348
+ def type_expr
349
+ @type_expr || (superclass.respond_to?(:type_expr) ? superclass.type_expr : nil)
350
+ end
351
+
352
+ # Add an argument to this field's signature, but
353
+ # also add some preparation hook methods which will be used for this argument
354
+ # @see {GraphQL::Schema::Argument#initialize} for the signature
355
+ def argument(*args, **kwargs, &block)
356
+ # Use `from_resolver: true` to short-circuit the InputObject's own `loads:` implementation
357
+ # so that we can support `#load_{x}` methods below.
358
+ super(*args, from_resolver: true, **kwargs)
359
+ end
360
+
361
+ # Registers new extension
362
+ # @param extension [Class] Extension class
363
+ # @param options [Hash] Optional extension options
364
+ def extension(extension, **options)
365
+ @own_extensions ||= []
366
+ @own_extensions << {extension => options}
367
+ end
368
+
369
+ # @api private
370
+ def extensions
371
+ own_exts = @own_extensions
372
+ # Jump through some hoops to avoid creating arrays when we don't actually need them
373
+ if superclass.respond_to?(:extensions)
374
+ s_exts = superclass.extensions
375
+ if own_exts
376
+ if s_exts.any?
377
+ own_exts + s_exts
378
+ else
379
+ own_exts
380
+ end
381
+ else
382
+ s_exts
383
+ end
384
+ else
385
+ own_exts || EMPTY_ARRAY
386
+ end
387
+ end
388
+
389
+ private
390
+
391
+ def own_extensions
392
+ @own_extensions
393
+ end
394
+ end
395
+ end
396
+ end
397
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ class Scalar < GraphQL::Schema::Member
5
+ extend GraphQL::Schema::Member::AcceptsDefinition
6
+ extend GraphQL::Schema::Member::ValidatesInput
7
+
8
+ class << self
9
+ def coerce_input(val, ctx)
10
+ val
11
+ end
12
+
13
+ def coerce_result(val, ctx)
14
+ val
15
+ end
16
+
17
+ def to_graphql
18
+ type_defn = GraphQL::ScalarType.new
19
+ type_defn.name = graphql_name
20
+ type_defn.description = description
21
+ type_defn.coerce_result = method(:coerce_result)
22
+ type_defn.coerce_input = method(:coerce_input)
23
+ type_defn.metadata[:type_class] = self
24
+ type_defn.default_scalar = default_scalar
25
+ type_defn.ast_node = ast_node
26
+ type_defn
27
+ end
28
+
29
+ def kind
30
+ GraphQL::TypeKinds::SCALAR
31
+ end
32
+
33
+ def default_scalar(is_default = nil)
34
+ if !is_default.nil?
35
+ @default_scalar = is_default
36
+ end
37
+ @default_scalar
38
+ end
39
+
40
+ def default_scalar?
41
+ @default_scalar ||= false
42
+ end
43
+
44
+ def validate_non_null_input(value, ctx)
45
+ result = Query::InputValidationResult.new
46
+ coerced_result = begin
47
+ ctx.query.with_error_handling do
48
+ coerce_input(value, ctx)
49
+ end
50
+ rescue GraphQL::CoercionError => err
51
+ err
52
+ end
53
+
54
+ if coerced_result.nil?
55
+ str_value = if value == Float::INFINITY
56
+ ""
57
+ else
58
+ " #{GraphQL::Language.serialize(value)}"
59
+ end
60
+ result.add_problem("Could not coerce value#{str_value} to #{graphql_name}")
61
+ elsif coerced_result.is_a?(GraphQL::CoercionError)
62
+ result.add_problem(coerced_result.message, message: coerced_result.message, extensions: coerced_result.extensions)
63
+ end
64
+ result
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ # This class can be extended to create fields on your subscription root.
6
+ #
7
+ # It provides hooks for the different parts of the subscription lifecycle:
8
+ #
9
+ # - `#authorized?`: called before initial subscription and subsequent updates
10
+ # - `#subscribe`: called for the initial subscription
11
+ # - `#update`: called for subsequent update
12
+ #
13
+ # Also, `#unsubscribe` terminates the subscription.
14
+ class Subscription < GraphQL::Schema::Resolver
15
+ extend GraphQL::Schema::Resolver::HasPayloadType
16
+ extend GraphQL::Schema::Member::HasFields
17
+ NO_UPDATE = :no_update
18
+ # The generated payload type is required; If there's no payload,
19
+ # propagate null.
20
+ null false
21
+
22
+ def initialize(object:, context:, field:)
23
+ super
24
+ # Figure out whether this is an update or an initial subscription
25
+ @mode = context.query.subscription_update? ? :update : :subscribe
26
+ end
27
+
28
+ def resolve_with_support(**args)
29
+ result = nil
30
+ unsubscribed = true
31
+ catch :graphql_subscription_unsubscribed do
32
+ result = super
33
+ unsubscribed = false
34
+ end
35
+
36
+
37
+ if unsubscribed
38
+ context.skip
39
+ else
40
+ result
41
+ end
42
+ end
43
+
44
+ # Implement the {Resolve} API
45
+ def resolve(**args)
46
+ # Dispatch based on `@mode`, which will raise a `NoMethodError` if we ever
47
+ # have an unexpected `@mode`
48
+ public_send("resolve_#{@mode}", **args)
49
+ end
50
+
51
+ # Wrap the user-defined `#subscribe` hook
52
+ def resolve_subscribe(**args)
53
+ ret_val = args.any? ? subscribe(**args) : subscribe
54
+ if ret_val == :no_response
55
+ context.skip
56
+ else
57
+ ret_val
58
+ end
59
+ end
60
+
61
+ # The default implementation returns nothing on subscribe.
62
+ # Override it to return an object or
63
+ # `:no_response` to (explicitly) return nothing.
64
+ def subscribe(args = {})
65
+ :no_response
66
+ end
67
+
68
+ # Wrap the user-provided `#update` hook
69
+ def resolve_update(**args)
70
+ ret_val = args.any? ? update(**args) : update
71
+ if ret_val == NO_UPDATE
72
+ context.namespace(:subscriptions)[:no_update] = true
73
+ context.skip
74
+ else
75
+ ret_val
76
+ end
77
+ end
78
+
79
+ # The default implementation returns the root object.
80
+ # Override it to return {NO_UPDATE} if you want to
81
+ # skip updates sometimes. Or override it to return a different object.
82
+ def update(args = {})
83
+ object
84
+ end
85
+
86
+ # If an argument is flagged with `loads:` and no object is found for it,
87
+ # remove this subscription (assuming that the object was deleted in the meantime,
88
+ # or that it became inaccessible).
89
+ def load_application_object_failed(err)
90
+ if @mode == :update
91
+ unsubscribe
92
+ end
93
+ super
94
+ end
95
+
96
+ # Call this to halt execution and remove this subscription from the system
97
+ def unsubscribe
98
+ context.namespace(:subscriptions)[:unsubscribed] = true
99
+ throw :graphql_subscription_unsubscribed
100
+ end
101
+
102
+ READING_SCOPE = ::Object.new
103
+ # Call this method to provide a new subscription_scope; OR
104
+ # call it without an argument to get the subscription_scope
105
+ # @param new_scope [Symbol]
106
+ # @param optional [Boolean] If true, then don't require `scope:` to be provided to updates to this subscription.
107
+ # @return [Symbol]
108
+ def self.subscription_scope(new_scope = READING_SCOPE, optional: false)
109
+ if new_scope != READING_SCOPE
110
+ @subscription_scope = new_scope
111
+ @subscription_scope_optional = optional
112
+ elsif defined?(@subscription_scope)
113
+ @subscription_scope
114
+ else
115
+ find_inherited_value(:subscription_scope)
116
+ end
117
+ end
118
+
119
+ def self.subscription_scope_optional?
120
+ if defined?(@subscription_scope_optional)
121
+ @subscription_scope_optional
122
+ else
123
+ find_inherited_value(:subscription_scope_optional, false)
124
+ end
125
+ end
126
+
127
+ # This is called during initial subscription to get a "name" for this subscription.
128
+ # Later, when `.trigger` is called, this will be called again to build another "name".
129
+ # Any subscribers with matching topic will begin the update flow.
130
+ #
131
+ # The default implementation creates a string using the field name, subscription scope, and argument keys and values.
132
+ # In that implementation, only `.trigger` calls with _exact matches_ result in updates to subscribers.
133
+ #
134
+ # To implement a filtered stream-type subscription flow, override this method to return a string with field name and subscription scope.
135
+ # Then, implement {#update} to compare its arguments to the current `object` and return {NO_UPDATE} when an
136
+ # update should be filtered out.
137
+ #
138
+ # @see {#update} for how to skip updates when an event comes with a matching topic.
139
+ # @param arguments [Hash<String => Object>] The arguments for this topic, in GraphQL-style (camelized strings)
140
+ # @param field [GraphQL::Schema::Field]
141
+ # @param scope [Object, nil] A value corresponding to `.trigger(... scope:)` (for updates) or the `subscription_scope` found in `context` (for initial subscriptions).
142
+ # @return [String] An identifier corresponding to a stream of updates
143
+ def self.topic_for(arguments:, field:, scope:)
144
+ Subscriptions::Serialize.dump_recursive([scope, field.graphql_name, arguments])
145
+ end
146
+
147
+ # Overriding Resolver#field_options to include subscription_scope
148
+ def self.field_options
149
+ super.merge(
150
+ subscription_scope: subscription_scope
151
+ )
152
+ end
153
+ end
154
+ end
155
+ end