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,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ # This plugin will stop resolving new fields after `max_seconds` have elapsed.
6
+ # After the time has passed, any remaining fields will be `nil`, with errors added
7
+ # to the `errors` key. Any already-resolved fields will be in the `data` key, so
8
+ # you'll get a partial response.
9
+ #
10
+ # You can subclass `GraphQL::Schema::Timeout` and override `max_seconds` and/or `handle_timeout`
11
+ # to provide custom logic when a timeout error occurs.
12
+ #
13
+ # Note that this will stop a query _in between_ field resolutions, but
14
+ # it doesn't interrupt long-running `resolve` functions. Be sure to use
15
+ # timeout options for external connections. For more info, see
16
+ # www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/
17
+ #
18
+ # @example Stop resolving fields after 2 seconds
19
+ # class MySchema < GraphQL::Schema
20
+ # use GraphQL::Schema::Timeout, max_seconds: 2
21
+ # end
22
+ #
23
+ # @example Notifying Bugsnag and logging a timeout
24
+ # class MyTimeout < GraphQL::Schema::Timeout
25
+ # def handle_timeout(error, query)
26
+ # Rails.logger.warn("GraphQL Timeout: #{error.message}: #{query.query_string}")
27
+ # Bugsnag.notify(error, {query_string: query.query_string})
28
+ # end
29
+ # end
30
+ #
31
+ # class MySchema < GraphQL::Schema
32
+ # use MyTimeout, max_seconds: 2
33
+ # end
34
+ #
35
+ class Timeout
36
+ def self.use(schema, **options)
37
+ tracer = new(**options)
38
+ schema.tracer(tracer)
39
+ end
40
+
41
+ # @param max_seconds [Numeric] how many seconds the query should be allowed to resolve new fields
42
+ def initialize(max_seconds:)
43
+ @max_seconds = max_seconds
44
+ end
45
+
46
+ def trace(key, data)
47
+ case key
48
+ when 'execute_multiplex'
49
+ data.fetch(:multiplex).queries.each do |query|
50
+ timeout_duration_s = max_seconds(query)
51
+ timeout_state = if timeout_duration_s == false
52
+ # if the method returns `false`, don't apply a timeout
53
+ false
54
+ else
55
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
56
+ timeout_at = now + (max_seconds(query) * 1000)
57
+ {
58
+ timeout_at: timeout_at,
59
+ timed_out: false
60
+ }
61
+ end
62
+ query.context.namespace(self.class)[:state] = timeout_state
63
+ end
64
+
65
+ yield
66
+ when 'execute_field', 'execute_field_lazy'
67
+ query_context = data[:context] || data[:query].context
68
+ timeout_state = query_context.namespace(self.class).fetch(:state)
69
+ # If the `:state` is `false`, then `max_seconds(query)` opted out of timeout for this query.
70
+ if timeout_state != false && Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) > timeout_state.fetch(:timeout_at)
71
+ error = if data[:context]
72
+ GraphQL::Schema::Timeout::TimeoutError.new(query_context.parent_type, query_context.field)
73
+ else
74
+ field = data.fetch(:field)
75
+ GraphQL::Schema::Timeout::TimeoutError.new(field.owner, field)
76
+ end
77
+
78
+ # Only invoke the timeout callback for the first timeout
79
+ if !timeout_state[:timed_out]
80
+ timeout_state[:timed_out] = true
81
+ handle_timeout(error, query_context.query)
82
+ end
83
+
84
+ error
85
+ else
86
+ yield
87
+ end
88
+ else
89
+ yield
90
+ end
91
+ end
92
+
93
+ # Called at the start of each query.
94
+ # The default implementation returns the `max_seconds:` value from installing this plugin.
95
+ #
96
+ # @param query [GraphQL::Query] The query that's about to run
97
+ # @return [Integer, false] The number of seconds after which to interrupt query execution and call {#handle_error}, or `false` to bypass the timeout.
98
+ def max_seconds(query)
99
+ @max_seconds
100
+ end
101
+
102
+ # Invoked when a query times out.
103
+ # @param error [GraphQL::Schema::Timeout::TimeoutError]
104
+ # @param query [GraphQL::Error]
105
+ def handle_timeout(error, query)
106
+ # override to do something interesting
107
+ end
108
+
109
+ # This error is raised when a query exceeds `max_seconds`.
110
+ # Since it's a child of {GraphQL::ExecutionError},
111
+ # its message will be added to the response's `errors` key.
112
+ #
113
+ # To raise an error that will stop query resolution, use a custom block
114
+ # to take this error and raise a new one which _doesn't_ descend from {GraphQL::ExecutionError},
115
+ # such as `RuntimeError`.
116
+ class TimeoutError < GraphQL::ExecutionError
117
+ def initialize(parent_type, field)
118
+ super("Timeout on #{parent_type.graphql_name}.#{field.graphql_name}")
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+ require "delegate"
3
+
4
+ module GraphQL
5
+ class Schema
6
+ # This middleware will stop resolving new fields after `max_seconds` have elapsed.
7
+ # After the time has passed, any remaining fields will be `nil`, with errors added
8
+ # to the `errors` key. Any already-resolved fields will be in the `data` key, so
9
+ # you'll get a partial response.
10
+ #
11
+ # You can provide a block which will be called with any timeout errors that occur.
12
+ #
13
+ # Note that this will stop a query _in between_ field resolutions, but
14
+ # it doesn't interrupt long-running `resolve` functions. Be sure to use
15
+ # timeout options for external connections. For more info, see
16
+ # www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/
17
+ #
18
+ # @example Stop resolving fields after 2 seconds
19
+ # MySchema.middleware << GraphQL::Schema::TimeoutMiddleware.new(max_seconds: 2)
20
+ #
21
+ # @example Notifying Bugsnag on a timeout
22
+ # MySchema.middleware << GraphQL::Schema::TimeoutMiddleware(max_seconds: 1.5) do |timeout_error, query|
23
+ # Bugsnag.notify(timeout_error, {query_string: query_ctx.query.query_string})
24
+ # end
25
+ #
26
+ # @api deprecated
27
+ # @see Schema::Timeout
28
+ class TimeoutMiddleware
29
+ # @param max_seconds [Numeric] how many seconds the query should be allowed to resolve new fields
30
+ def initialize(max_seconds:, context_key: nil, &block)
31
+ @max_seconds = max_seconds
32
+ if context_key
33
+ GraphQL::Deprecation.warn("TimeoutMiddleware's `context_key` is ignored, timeout data is now stored in isolated storage")
34
+ end
35
+ @error_handler = block
36
+ end
37
+
38
+ def call(parent_type, parent_object, field_definition, field_args, query_context)
39
+ ns = query_context.namespace(self.class)
40
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
41
+ timeout_at = ns[:timeout_at] ||= now + @max_seconds
42
+
43
+ if timeout_at < now
44
+ on_timeout(parent_type, parent_object, field_definition, field_args, query_context)
45
+ else
46
+ yield
47
+ end
48
+ end
49
+
50
+ # This is called when a field _would_ be resolved, except that we're over the time limit.
51
+ # @return [GraphQL::Schema::TimeoutMiddleware::TimeoutError] An error whose message will be added to the `errors` key
52
+ def on_timeout(parent_type, parent_object, field_definition, field_args, field_context)
53
+ err = GraphQL::Schema::TimeoutMiddleware::TimeoutError.new(parent_type, field_definition)
54
+ if @error_handler
55
+ query_proxy = TimeoutQueryProxy.new(field_context.query, field_context)
56
+ @error_handler.call(err, query_proxy)
57
+ end
58
+ err
59
+ end
60
+
61
+ # This behaves like {GraphQL::Query} but {#context} returns
62
+ # the _field-level_ context, not the query-level context.
63
+ # This means you can reliably get the `irep_node` and `path`
64
+ # from it after the fact.
65
+ class TimeoutQueryProxy < SimpleDelegator
66
+ def initialize(query, ctx)
67
+ @context = ctx
68
+ super(query)
69
+ end
70
+
71
+ attr_reader :context
72
+ end
73
+
74
+ # This error is raised when a query exceeds `max_seconds`.
75
+ # Since it's a child of {GraphQL::ExecutionError},
76
+ # its message will be added to the response's `errors` key.
77
+ #
78
+ # To raise an error that will stop query resolution, use a custom block
79
+ # to take this error and raise a new one which _doesn't_ descend from {GraphQL::ExecutionError},
80
+ # such as `RuntimeError`.
81
+ class TimeoutError < GraphQL::ExecutionError
82
+ def initialize(parent_type, field_defn)
83
+ super("Timeout on #{parent_type.name}.#{field_defn.name}")
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ # Visit the members of this schema and build up artifacts for runtime.
5
+ # @api private
6
+ class Traversal
7
+ # @return [Hash<String => GraphQL::BaseType]
8
+ attr_reader :type_map
9
+
10
+ # @return [Hash<String => Hash<String => GraphQL::Field>>]
11
+ attr_reader :instrumented_field_map
12
+
13
+ # @return [Hash<String => Array<GraphQL::Field || GraphQL::Argument || GraphQL::Directive>]
14
+ attr_reader :type_reference_map
15
+
16
+ # @return [Hash<String => Array<GraphQL::BaseType>]
17
+ attr_reader :union_memberships
18
+
19
+
20
+ # @param schema [GraphQL::Schema]
21
+ def initialize(schema, introspection: true)
22
+ @schema = schema
23
+ @introspection = introspection
24
+ built_in_insts = [
25
+ GraphQL::Relay::ConnectionInstrumentation,
26
+ GraphQL::Relay::EdgesInstrumentation,
27
+ GraphQL::Relay::Mutation::Instrumentation,
28
+ ]
29
+
30
+ if schema.query_execution_strategy != GraphQL::Execution::Interpreter
31
+ built_in_insts << GraphQL::Schema::Member::Instrumentation
32
+ end
33
+
34
+ @field_instrumenters =
35
+ schema.instrumenters[:field] +
36
+ built_in_insts +
37
+ schema.instrumenters[:field_after_built_ins]
38
+
39
+ # These fields have types specified by _name_,
40
+ # So we need to inspect the schema and find those types,
41
+ # then update their references.
42
+ @late_bound_fields = []
43
+ @type_map = {}
44
+ @instrumented_field_map = Hash.new { |h, k| h[k] = {} }
45
+ @type_reference_map = Hash.new { |h, k| h[k] = [] }
46
+ @union_memberships = Hash.new { |h, k| h[k] = [] }
47
+ visit(schema, schema, nil)
48
+ resolve_late_bound_fields
49
+ end
50
+
51
+ private
52
+
53
+ # A brute-force appraoch to late binding.
54
+ # Just keep trying the whole list, hoping that they
55
+ # eventually all resolve.
56
+ # This could be replaced with proper dependency tracking.
57
+ def resolve_late_bound_fields
58
+ # This is a bit tricky, with the writes going to internal state.
59
+ prev_late_bound_fields = @late_bound_fields
60
+ # Things might get added here during `visit...`
61
+ # or they might be added manually if we can't find them by hand
62
+ @late_bound_fields = []
63
+ prev_late_bound_fields.each do |(owner_type, field_defn, dynamic_field)|
64
+ if @type_map.key?(field_defn.type.unwrap.name)
65
+ late_bound_return_type = field_defn.type
66
+ resolved_type = @type_map.fetch(late_bound_return_type.unwrap.name)
67
+ wrapped_resolved_type = rewrap_resolved_type(late_bound_return_type, resolved_type)
68
+ # Update the field definition in place? :thinking_face:
69
+ field_defn.type = wrapped_resolved_type
70
+ visit_field_on_type(@schema, owner_type, field_defn, dynamic_field: dynamic_field)
71
+ else
72
+ @late_bound_fields << [owner_type, field_defn, dynamic_field]
73
+ end
74
+ end
75
+
76
+ if @late_bound_fields.any?
77
+ # If we visited each field and failed to resolve _any_,
78
+ # then we're stuck.
79
+ if @late_bound_fields == prev_late_bound_fields
80
+ type_names = prev_late_bound_fields.map { |f| f[1] }.map(&:type).map(&:unwrap).map(&:name).uniq
81
+ raise <<-ERR
82
+ Some late-bound types couldn't be resolved:
83
+
84
+ - #{type_names}
85
+ - Found __* types: #{@type_map.keys.select { |k| k.start_with?("__") }}
86
+ ERR
87
+ else
88
+ resolve_late_bound_fields
89
+ end
90
+ end
91
+ end
92
+
93
+ # The late-bound type may be wrapped with list or non-null types.
94
+ # Apply the same wrapping to the resolve type and
95
+ # return the maybe-wrapped type
96
+ def rewrap_resolved_type(late_bound_type, resolved_inner_type)
97
+ case late_bound_type
98
+ when GraphQL::NonNullType
99
+ rewrap_resolved_type(late_bound_type.of_type, resolved_inner_type).to_non_null_type
100
+ when GraphQL::ListType
101
+ rewrap_resolved_type(late_bound_type.of_type, resolved_inner_type).to_list_type
102
+ when GraphQL::Schema::LateBoundType
103
+ resolved_inner_type
104
+ else
105
+ raise "Unexpected late_bound_type: #{late_bound_type.inspect} (#{late_bound_type.class})"
106
+ end
107
+ end
108
+
109
+ def visit(schema, member, context_description)
110
+ case member
111
+ when GraphQL::Schema
112
+ member.directives.each { |name, directive| visit(schema, directive, "Directive #{name}") }
113
+ # Find the starting points, then visit them
114
+ visit_roots = [member.query, member.mutation, member.subscription]
115
+ if @introspection
116
+ introspection_types = schema.introspection_system.types.values
117
+ visit_roots.concat(introspection_types)
118
+ if member.query
119
+ member.introspection_system.entry_points.each do |introspection_field|
120
+ # Visit this so that arguments class is preconstructed
121
+ # Skip validation since it begins with "__"
122
+ visit_field_on_type(schema, member.query, introspection_field, dynamic_field: true)
123
+ end
124
+ end
125
+ end
126
+ visit_roots.concat(member.orphan_types)
127
+ visit_roots.compact!
128
+ visit_roots.each { |t| visit(schema, t, t.name) }
129
+ when GraphQL::Directive
130
+ member.arguments.each do |name, argument|
131
+ @type_reference_map[argument.type.unwrap.to_s] << argument
132
+ visit(schema, argument.type, "Directive argument #{member.name}.#{name}")
133
+ end
134
+ # Construct arguments class here, which is later used to generate GraphQL::Query::Arguments
135
+ # to be passed to a resolver proc
136
+ GraphQL::Query::Arguments.construct_arguments_class(member)
137
+ when GraphQL::BaseType
138
+ type_defn = member.unwrap
139
+ prev_type = @type_map[type_defn.name]
140
+ # Continue to visit this type if it's the first time we've seen it:
141
+ if prev_type.nil?
142
+ validate_type(type_defn, context_description)
143
+ @type_map[type_defn.name] = type_defn
144
+ case type_defn
145
+ when GraphQL::ObjectType
146
+ type_defn.interfaces.each { |i| visit(schema, i, "Interface on #{type_defn.name}") }
147
+ visit_fields(schema, type_defn)
148
+ when GraphQL::InterfaceType
149
+ visit_fields(schema, type_defn)
150
+ type_defn.orphan_types.each do |t|
151
+ visit(schema, t, "Orphan type for #{type_defn.name}")
152
+ end
153
+ when GraphQL::UnionType
154
+ type_defn.possible_types.each do |t|
155
+ @union_memberships[t.name] << type_defn
156
+ visit(schema, t, "Possible type for #{type_defn.name}")
157
+ end
158
+ when GraphQL::InputObjectType
159
+ type_defn.arguments.each do |name, arg|
160
+ @type_reference_map[arg.type.unwrap.to_s] << arg
161
+ visit(schema, arg.type, "Input field #{type_defn.name}.#{name}")
162
+ end
163
+
164
+ # Construct arguments class here, which is later used to generate GraphQL::Query::Arguments
165
+ # to be passed to a resolver proc
166
+ if type_defn.arguments_class.nil?
167
+ GraphQL::Query::Arguments.construct_arguments_class(type_defn)
168
+ end
169
+ end
170
+ elsif !prev_type.equal?(type_defn)
171
+ # If the previous entry in the map isn't the same object we just found, raise.
172
+ raise("Duplicate type definition found for name '#{type_defn.name}' at '#{context_description}' (#{prev_type.metadata[:type_class] || prev_type}, #{type_defn.metadata[:type_class] || type_defn})")
173
+ end
174
+ when Class
175
+ if member.respond_to?(:graphql_definition)
176
+ graphql_member = member.graphql_definition
177
+ visit(schema, graphql_member, context_description)
178
+ else
179
+ raise GraphQL::Schema::InvalidTypeError.new("Unexpected traversal member: #{member} (#{member.class.name})")
180
+ end
181
+ else
182
+ message = "Unexpected schema traversal member: #{member} (#{member.class.name})"
183
+ raise GraphQL::Schema::InvalidTypeError.new(message)
184
+ end
185
+ end
186
+
187
+ def visit_fields(schema, type_defn)
188
+ type_defn.all_fields.each do |field_defn|
189
+ visit_field_on_type(schema, type_defn, field_defn)
190
+ end
191
+ end
192
+
193
+ def visit_field_on_type(schema, type_defn, field_defn, dynamic_field: false)
194
+ base_return_type = field_defn.type.unwrap
195
+ if base_return_type.is_a?(GraphQL::Schema::LateBoundType)
196
+ @late_bound_fields << [type_defn, field_defn, dynamic_field]
197
+ return
198
+ end
199
+ if dynamic_field
200
+ # Don't apply instrumentation to dynamic fields since they're shared constants
201
+ instrumented_field_defn = field_defn
202
+ else
203
+ instrumented_field_defn = @field_instrumenters.reduce(field_defn) do |defn, inst|
204
+ inst.instrument(type_defn, defn)
205
+ end
206
+ @instrumented_field_map[type_defn.name][instrumented_field_defn.name] = instrumented_field_defn
207
+ end
208
+ @type_reference_map[instrumented_field_defn.type.unwrap.name] << instrumented_field_defn
209
+ visit(schema, instrumented_field_defn.type, "Field #{type_defn.name}.#{instrumented_field_defn.name}'s return type")
210
+ instrumented_field_defn.arguments.each do |name, arg|
211
+ @type_reference_map[arg.type.unwrap.to_s] << arg
212
+ visit(schema, arg.type, "Argument #{name} on #{type_defn.name}.#{instrumented_field_defn.name}")
213
+ end
214
+
215
+ # Construct arguments class here, which is later used to generate GraphQL::Query::Arguments
216
+ # to be passed to a resolver proc
217
+ GraphQL::Query::Arguments.construct_arguments_class(instrumented_field_defn)
218
+ end
219
+
220
+ def validate_type(member, context_description)
221
+ error_message = GraphQL::Schema::Validation.validate(member)
222
+ if error_message
223
+ raise GraphQL::Schema::InvalidTypeError.new("#{context_description} is invalid: #{error_message}")
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ # @api private
5
+ module TypeExpression
6
+ # Fetch a type from a type map by its AST specification.
7
+ # Return `nil` if not found.
8
+ # @param type_owner [#get_type] A thing for looking up types by name
9
+ # @param ast_node [GraphQL::Language::Nodes::AbstractNode]
10
+ # @return [Class, GraphQL::Schema::NonNull, GraphQL::Schema:List]
11
+ def self.build_type(type_owner, ast_node)
12
+ case ast_node
13
+ when GraphQL::Language::Nodes::TypeName
14
+ type_owner.get_type(ast_node.name) # rubocop:disable Development/ContextIsPassedCop -- this is a `context` or `warden`, it's already query-aware
15
+ when GraphQL::Language::Nodes::NonNullType
16
+ ast_inner_type = ast_node.of_type
17
+ inner_type = build_type(type_owner, ast_inner_type)
18
+ wrap_type(inner_type, :to_non_null_type)
19
+ when GraphQL::Language::Nodes::ListType
20
+ ast_inner_type = ast_node.of_type
21
+ inner_type = build_type(type_owner, ast_inner_type)
22
+ wrap_type(inner_type, :to_list_type)
23
+ else
24
+ raise "Invariant: unexpected type from ast: #{ast_node.inspect}"
25
+ end
26
+ end
27
+
28
+ class << self
29
+ private
30
+
31
+ def wrap_type(type, wrapper_method)
32
+ if type.nil?
33
+ nil
34
+ elsif wrapper_method == :to_list_type || wrapper_method == :to_non_null_type
35
+ type.public_send(wrapper_method)
36
+ else
37
+ raise ArgumentError, "Unexpected wrapper method: #{wrapper_method.inspect}"
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ class Schema
5
+ # This class joins an object type to an abstract type (interface or union) of which
6
+ # it is a member.
7
+ class TypeMembership
8
+ # @return [Class<GraphQL::Schema::Object>]
9
+ attr_accessor :object_type
10
+
11
+ # @return [Class<GraphQL::Schema::Union>, Module<GraphQL::Schema::Interface>]
12
+ attr_reader :abstract_type
13
+
14
+ # Called when an object is hooked up to an abstract type, such as {Schema::Union.possible_types}
15
+ # or {Schema::Object.implements} (for interfaces).
16
+ #
17
+ # @param abstract_type [Class<GraphQL::Schema::Union>, Module<GraphQL::Schema::Interface>]
18
+ # @param object_type [Class<GraphQL::Schema::Object>]
19
+ # @param options [Hash] Any options passed to `.possible_types` or `.implements`
20
+ def initialize(abstract_type, object_type, **options)
21
+ @abstract_type = abstract_type
22
+ @object_type = object_type
23
+ @options = options
24
+ end
25
+
26
+ # @return [Boolean] if false, {#object_type} will be treated as _not_ a member of {#abstract_type}
27
+ def visible?(ctx)
28
+ warden = Warden.from_context(ctx)
29
+ (@object_type.respond_to?(:visible?) ? warden.visible_type?(@object_type, ctx) : true) &&
30
+ (@abstract_type.respond_to?(:visible?) ? warden.visible_type?(@abstract_type, ctx) : true)
31
+ end
32
+
33
+ def graphql_name
34
+ "#{@object_type.graphql_name}.#{@abstract_type.kind.interface? ? "implements" : "belongsTo" }.#{@abstract_type.graphql_name}"
35
+ end
36
+
37
+ def path
38
+ graphql_name
39
+ end
40
+
41
+ def inspect
42
+ "#<#{self.class} #{@object_type.inspect} => #{@abstract_type.inspect}>"
43
+ end
44
+
45
+ alias :type_class :itself
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ class Schema
4
+ class Union < GraphQL::Schema::Member
5
+ extend GraphQL::Schema::Member::AcceptsDefinition
6
+ extend GraphQL::Schema::Member::HasUnresolvedTypeError
7
+
8
+ class << self
9
+ def inherited(child_class)
10
+ add_unresolved_type_error(child_class)
11
+ super
12
+ end
13
+
14
+ def possible_types(*types, context: GraphQL::Query::NullContext, **options)
15
+ if types.any?
16
+ types.each do |t|
17
+ assert_valid_union_member(t)
18
+ type_memberships << type_membership_class.new(self, t, **options)
19
+ end
20
+ else
21
+ visible_types = []
22
+ warden = Warden.from_context(context)
23
+ type_memberships.each do |type_membership|
24
+ if warden.visible_type_membership?(type_membership, context)
25
+ visible_types << type_membership.object_type
26
+ end
27
+ end
28
+ visible_types
29
+ end
30
+ end
31
+
32
+ def all_possible_types
33
+ type_memberships.map(&:object_type)
34
+ end
35
+
36
+ def to_graphql
37
+ type_defn = GraphQL::UnionType.new
38
+ type_defn.name = graphql_name
39
+ type_defn.description = description
40
+ type_defn.ast_node = ast_node
41
+ type_defn.type_memberships = type_memberships
42
+ if respond_to?(:resolve_type)
43
+ type_defn.resolve_type = method(:resolve_type)
44
+ end
45
+ type_defn.metadata[:type_class] = self
46
+ type_defn
47
+ end
48
+
49
+ def type_membership_class(membership_class = nil)
50
+ if membership_class
51
+ @type_membership_class = membership_class
52
+ else
53
+ @type_membership_class || find_inherited_value(:type_membership_class, GraphQL::Schema::TypeMembership)
54
+ end
55
+ end
56
+
57
+ def kind
58
+ GraphQL::TypeKinds::UNION
59
+ end
60
+
61
+ def type_memberships
62
+ @type_memberships ||= []
63
+ end
64
+
65
+ # Update a type membership whose `.object_type` is a string or late-bound type
66
+ # so that the type membership's `.object_type` is the given `object_type`.
67
+ # (This is used for updating the union after the schema as lazily loaded the union member.)
68
+ # @api private
69
+ def assign_type_membership_object_type(object_type)
70
+ assert_valid_union_member(object_type)
71
+ type_memberships.each { |tm|
72
+ possible_type = tm.object_type
73
+ if possible_type.is_a?(String) && (possible_type == object_type.name)
74
+ # This is a match of Ruby class names, not graphql names,
75
+ # since strings are used to refer to constants.
76
+ tm.object_type = object_type
77
+ elsif possible_type.is_a?(LateBoundType) && possible_type.graphql_name == object_type.graphql_name
78
+ tm.object_type = object_type
79
+ end
80
+ }
81
+ nil
82
+ end
83
+
84
+ private
85
+
86
+ def assert_valid_union_member(type_defn)
87
+ if type_defn.is_a?(Module) && !type_defn.is_a?(Class)
88
+ # it's an interface type, defined as a module
89
+ raise ArgumentError, "Union possible_types can only be object types (not interface types), remove #{type_defn.graphql_name} (#{type_defn.inspect})"
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+ require 'graphql/schema/base_64_bp'
3
+
4
+ module GraphQL
5
+ class Schema
6
+ module UniqueWithinType
7
+ class << self
8
+ attr_accessor :default_id_separator
9
+ end
10
+ self.default_id_separator = "-"
11
+
12
+ module_function
13
+
14
+ # @param type_name [String]
15
+ # @param object_value [Any]
16
+ # @return [String] a unique, opaque ID generated as a function of the two inputs
17
+ def encode(type_name, object_value, separator: self.default_id_separator)
18
+ object_value_str = object_value.to_s
19
+
20
+ if type_name.include?(separator)
21
+ raise "encode(#{type_name}, #{object_value_str}) contains reserved characters `#{separator}` in the type name"
22
+ end
23
+
24
+ Base64.strict_encode64([type_name, object_value_str].join(separator))
25
+ end
26
+
27
+ # @param node_id [String] A unique ID generated by {.encode}
28
+ # @return [Array<(String, String)>] The type name & value passed to {.encode}
29
+ def decode(node_id, separator: self.default_id_separator)
30
+ GraphQL::Schema::Base64Encoder.decode(node_id).split(separator, 2)
31
+ end
32
+ end
33
+ end
34
+ end