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,418 @@
1
+ # frozen_string_literal: true
2
+
3
+ # frozen_string_literal: true
4
+ module GraphQL
5
+ module StaticValidation
6
+ module FieldsWillMerge
7
+ # Validates that a selection set is valid if all fields (including spreading any
8
+ # fragments) either correspond to distinct response names or can be merged
9
+ # without ambiguity.
10
+ #
11
+ # Original Algorithm: https://github.com/graphql/graphql-js/blob/master/src/validation/rules/OverlappingFieldsCanBeMerged.js
12
+ NO_ARGS = {}.freeze
13
+
14
+ Field = Struct.new(:node, :definition, :owner_type, :parents)
15
+ FragmentSpread = Struct.new(:name, :parents)
16
+
17
+ def initialize(*)
18
+ super
19
+ @visited_fragments = {}
20
+ @compared_fragments = {}
21
+ @conflict_count = 0
22
+ end
23
+
24
+ def on_operation_definition(node, _parent)
25
+ setting_errors { conflicts_within_selection_set(node, type_definition) }
26
+ super
27
+ end
28
+
29
+ def on_field(node, _parent)
30
+ setting_errors { conflicts_within_selection_set(node, type_definition) }
31
+ super
32
+ end
33
+
34
+ private
35
+
36
+ def field_conflicts
37
+ @field_conflicts ||= Hash.new do |errors, field|
38
+ errors[field] = GraphQL::StaticValidation::FieldsWillMergeError.new(kind: :field, field_name: field)
39
+ end
40
+ end
41
+
42
+ def arg_conflicts
43
+ @arg_conflicts ||= Hash.new do |errors, field|
44
+ errors[field] = GraphQL::StaticValidation::FieldsWillMergeError.new(kind: :argument, field_name: field)
45
+ end
46
+ end
47
+
48
+ def setting_errors
49
+ @field_conflicts = nil
50
+ @arg_conflicts = nil
51
+
52
+ yield
53
+
54
+ field_conflicts.each_value { |error| add_error(error) }
55
+ arg_conflicts.each_value { |error| add_error(error) }
56
+ end
57
+
58
+ def conflicts_within_selection_set(node, parent_type)
59
+ return if parent_type.nil?
60
+
61
+ fields, fragment_spreads = fields_and_fragments_from_selection(node, owner_type: parent_type, parents: [])
62
+
63
+ # (A) Find find all conflicts "within" the fields of this selection set.
64
+ find_conflicts_within(fields)
65
+
66
+ fragment_spreads.each_with_index do |fragment_spread, i|
67
+ are_mutually_exclusive = mutually_exclusive?(
68
+ fragment_spread.parents,
69
+ [parent_type]
70
+ )
71
+
72
+ # (B) Then find conflicts between these fields and those represented by
73
+ # each spread fragment name found.
74
+ find_conflicts_between_fields_and_fragment(
75
+ fragment_spread,
76
+ fields,
77
+ mutually_exclusive: are_mutually_exclusive,
78
+ )
79
+
80
+ # (C) Then compare this fragment with all other fragments found in this
81
+ # selection set to collect conflicts between fragments spread together.
82
+ # This compares each item in the list of fragment names to every other
83
+ # item in that same list (except for itself).
84
+ fragment_spreads[i + 1..-1].each do |fragment_spread2|
85
+ are_mutually_exclusive = mutually_exclusive?(
86
+ fragment_spread.parents,
87
+ fragment_spread2.parents
88
+ )
89
+
90
+ find_conflicts_between_fragments(
91
+ fragment_spread,
92
+ fragment_spread2,
93
+ mutually_exclusive: are_mutually_exclusive,
94
+ )
95
+ end
96
+ end
97
+ end
98
+
99
+ def find_conflicts_between_fragments(fragment_spread1, fragment_spread2, mutually_exclusive:)
100
+ fragment_name1 = fragment_spread1.name
101
+ fragment_name2 = fragment_spread2.name
102
+ return if fragment_name1 == fragment_name2
103
+
104
+ cache_key = compared_fragments_key(
105
+ fragment_name1,
106
+ fragment_name2,
107
+ mutually_exclusive,
108
+ )
109
+ if @compared_fragments.key?(cache_key)
110
+ return
111
+ else
112
+ @compared_fragments[cache_key] = true
113
+ end
114
+
115
+ fragment1 = context.fragments[fragment_name1]
116
+ fragment2 = context.fragments[fragment_name2]
117
+
118
+ return if fragment1.nil? || fragment2.nil?
119
+
120
+ fragment_type1 = context.warden.get_type(fragment1.type.name)
121
+ fragment_type2 = context.warden.get_type(fragment2.type.name)
122
+
123
+ return if fragment_type1.nil? || fragment_type2.nil?
124
+
125
+ fragment_fields1, fragment_spreads1 = fields_and_fragments_from_selection(
126
+ fragment1,
127
+ owner_type: fragment_type1,
128
+ parents: [*fragment_spread1.parents, fragment_type1]
129
+ )
130
+ fragment_fields2, fragment_spreads2 = fields_and_fragments_from_selection(
131
+ fragment2,
132
+ owner_type: fragment_type1,
133
+ parents: [*fragment_spread2.parents, fragment_type2]
134
+ )
135
+
136
+ # (F) First, find all conflicts between these two collections of fields
137
+ # (not including any nested fragments).
138
+ find_conflicts_between(
139
+ fragment_fields1,
140
+ fragment_fields2,
141
+ mutually_exclusive: mutually_exclusive,
142
+ )
143
+
144
+ # (G) Then collect conflicts between the first fragment and any nested
145
+ # fragments spread in the second fragment.
146
+ fragment_spreads2.each do |fragment_spread|
147
+ find_conflicts_between_fragments(
148
+ fragment_spread1,
149
+ fragment_spread,
150
+ mutually_exclusive: mutually_exclusive,
151
+ )
152
+ end
153
+
154
+ # (G) Then collect conflicts between the first fragment and any nested
155
+ # fragments spread in the second fragment.
156
+ fragment_spreads1.each do |fragment_spread|
157
+ find_conflicts_between_fragments(
158
+ fragment_spread2,
159
+ fragment_spread,
160
+ mutually_exclusive: mutually_exclusive,
161
+ )
162
+ end
163
+ end
164
+
165
+ def find_conflicts_between_fields_and_fragment(fragment_spread, fields, mutually_exclusive:)
166
+ fragment_name = fragment_spread.name
167
+ return if @visited_fragments.key?(fragment_name)
168
+ @visited_fragments[fragment_name] = true
169
+
170
+ fragment = context.fragments[fragment_name]
171
+ return if fragment.nil?
172
+
173
+ fragment_type = context.warden.get_type(fragment.type.name)
174
+ return if fragment_type.nil?
175
+
176
+ fragment_fields, fragment_spreads = fields_and_fragments_from_selection(fragment, owner_type: fragment_type, parents: [*fragment_spread.parents, fragment_type])
177
+
178
+ # (D) First find any conflicts between the provided collection of fields
179
+ # and the collection of fields represented by the given fragment.
180
+ find_conflicts_between(
181
+ fields,
182
+ fragment_fields,
183
+ mutually_exclusive: mutually_exclusive,
184
+ )
185
+
186
+ # (E) Then collect any conflicts between the provided collection of fields
187
+ # and any fragment names found in the given fragment.
188
+ fragment_spreads.each do |fragment_spread|
189
+ find_conflicts_between_fields_and_fragment(
190
+ fragment_spread,
191
+ fields,
192
+ mutually_exclusive: mutually_exclusive,
193
+ )
194
+ end
195
+ end
196
+
197
+ def find_conflicts_within(response_keys)
198
+ response_keys.each do |key, fields|
199
+ next if fields.size < 2
200
+ # find conflicts within nodes
201
+ for i in 0..fields.size - 1
202
+ for j in i + 1..fields.size - 1
203
+ find_conflict(key, fields[i], fields[j])
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ def find_conflict(response_key, field1, field2, mutually_exclusive: false)
210
+ return if @conflict_count >= context.max_errors
211
+
212
+ node1 = field1.node
213
+ node2 = field2.node
214
+
215
+ are_mutually_exclusive = mutually_exclusive ||
216
+ mutually_exclusive?(field1.parents, field2.parents)
217
+
218
+ if !are_mutually_exclusive
219
+ if node1.name != node2.name
220
+ conflict = field_conflicts[response_key]
221
+
222
+ conflict.add_conflict(node1, node1.name)
223
+ conflict.add_conflict(node2, node2.name)
224
+
225
+ @conflict_count += 1
226
+ end
227
+
228
+ if !same_arguments?(node1, node2)
229
+ conflict = arg_conflicts[response_key]
230
+
231
+ conflict.add_conflict(node1, GraphQL::Language.serialize(serialize_field_args(node1)))
232
+ conflict.add_conflict(node2, GraphQL::Language.serialize(serialize_field_args(node2)))
233
+
234
+ @conflict_count += 1
235
+ end
236
+ end
237
+
238
+ find_conflicts_between_sub_selection_sets(
239
+ field1,
240
+ field2,
241
+ mutually_exclusive: are_mutually_exclusive,
242
+ )
243
+ end
244
+
245
+ def find_conflicts_between_sub_selection_sets(field1, field2, mutually_exclusive:)
246
+ return if field1.definition.nil? || field2.definition.nil?
247
+
248
+ return_type1 = field1.definition.type.unwrap
249
+ return_type2 = field2.definition.type.unwrap
250
+ parents1 = [return_type1]
251
+ parents2 = [return_type2]
252
+
253
+ fields, fragment_spreads = fields_and_fragments_from_selection(
254
+ field1.node,
255
+ owner_type: return_type1,
256
+ parents: parents1
257
+ )
258
+
259
+ fields2, fragment_spreads2 = fields_and_fragments_from_selection(
260
+ field2.node,
261
+ owner_type: return_type2,
262
+ parents: parents2
263
+ )
264
+
265
+ # (H) First, collect all conflicts between these two collections of field.
266
+ find_conflicts_between(fields, fields2, mutually_exclusive: mutually_exclusive)
267
+
268
+ # (I) Then collect conflicts between the first collection of fields and
269
+ # those referenced by each fragment name associated with the second.
270
+ fragment_spreads2.each do |fragment_spread|
271
+ find_conflicts_between_fields_and_fragment(
272
+ fragment_spread,
273
+ fields,
274
+ mutually_exclusive: mutually_exclusive,
275
+ )
276
+ end
277
+
278
+ # (I) Then collect conflicts between the second collection of fields and
279
+ # those referenced by each fragment name associated with the first.
280
+ fragment_spreads.each do |fragment_spread|
281
+ find_conflicts_between_fields_and_fragment(
282
+ fragment_spread,
283
+ fields2,
284
+ mutually_exclusive: mutually_exclusive,
285
+ )
286
+ end
287
+
288
+ # (J) Also collect conflicts between any fragment names by the first and
289
+ # fragment names by the second. This compares each item in the first set of
290
+ # names to each item in the second set of names.
291
+ fragment_spreads.each do |frag1|
292
+ fragment_spreads2.each do |frag2|
293
+ find_conflicts_between_fragments(
294
+ frag1,
295
+ frag2,
296
+ mutually_exclusive: mutually_exclusive
297
+ )
298
+ end
299
+ end
300
+ end
301
+
302
+ def find_conflicts_between(response_keys, response_keys2, mutually_exclusive:)
303
+ response_keys.each do |key, fields|
304
+ fields2 = response_keys2[key]
305
+ if fields2
306
+ fields.each do |field|
307
+ fields2.each do |field2|
308
+ find_conflict(
309
+ key,
310
+ field,
311
+ field2,
312
+ mutually_exclusive: mutually_exclusive,
313
+ )
314
+ end
315
+ end
316
+ end
317
+ end
318
+ end
319
+
320
+ NO_SELECTIONS = [{}.freeze, [].freeze].freeze
321
+
322
+ def fields_and_fragments_from_selection(node, owner_type:, parents:)
323
+ if node.selections.empty?
324
+ NO_SELECTIONS
325
+ else
326
+ fields, fragment_spreads = find_fields_and_fragments(node.selections, owner_type: owner_type, parents: parents, fields: [], fragment_spreads: [])
327
+ response_keys = fields.group_by { |f| f.node.alias || f.node.name }
328
+ [response_keys, fragment_spreads]
329
+ end
330
+ end
331
+
332
+ def find_fields_and_fragments(selections, owner_type:, parents:, fields:, fragment_spreads:)
333
+ selections.each do |node|
334
+ case node
335
+ when GraphQL::Language::Nodes::Field
336
+ definition = context.query.get_field(owner_type, node.name)
337
+ fields << Field.new(node, definition, owner_type, parents)
338
+ when GraphQL::Language::Nodes::InlineFragment
339
+ fragment_type = node.type ? context.warden.get_type(node.type.name) : owner_type
340
+ find_fields_and_fragments(node.selections, parents: [*parents, fragment_type], owner_type: owner_type, fields: fields, fragment_spreads: fragment_spreads) if fragment_type
341
+ when GraphQL::Language::Nodes::FragmentSpread
342
+ fragment_spreads << FragmentSpread.new(node.name, parents)
343
+ end
344
+ end
345
+
346
+ [fields, fragment_spreads]
347
+ end
348
+
349
+ def same_arguments?(field1, field2)
350
+ # Check for incompatible / non-identical arguments on this node:
351
+ arguments1 = field1.arguments
352
+ arguments2 = field2.arguments
353
+
354
+ return false if arguments1.length != arguments2.length
355
+
356
+ arguments1.all? do |argument1|
357
+ argument2 = arguments2.find { |argument| argument.name == argument1.name }
358
+ return false if argument2.nil?
359
+
360
+ serialize_arg(argument1.value) == serialize_arg(argument2.value)
361
+ end
362
+ end
363
+
364
+ def serialize_arg(arg_value)
365
+ case arg_value
366
+ when GraphQL::Language::Nodes::AbstractNode
367
+ arg_value.to_query_string
368
+ when Array
369
+ "[#{arg_value.map { |a| serialize_arg(a) }.join(", ")}]"
370
+ else
371
+ GraphQL::Language.serialize(arg_value)
372
+ end
373
+ end
374
+
375
+ def serialize_field_args(field)
376
+ serialized_args = {}
377
+ field.arguments.each do |argument|
378
+ serialized_args[argument.name] = serialize_arg(argument.value)
379
+ end
380
+ serialized_args
381
+ end
382
+
383
+ def compared_fragments_key(frag1, frag2, exclusive)
384
+ # Cache key to not compare two fragments more than once.
385
+ # The key includes both fragment names sorted (this way we
386
+ # avoid computing "A vs B" and "B vs A"). It also includes
387
+ # "exclusive" since the result may change depending on the parent_type
388
+ "#{[frag1, frag2].sort.join('-')}-#{exclusive}"
389
+ end
390
+
391
+ # Given two list of parents, find out if they are mutually exclusive
392
+ # In this context, `parents` represends the "self scope" of the field,
393
+ # what types may be found at this point in the query.
394
+ def mutually_exclusive?(parents1, parents2)
395
+ if parents1.empty? || parents2.empty?
396
+ false
397
+ elsif parents1.length == parents2.length
398
+ parents1.length.times.any? do |i|
399
+ type1 = parents1[i - 1]
400
+ type2 = parents2[i - 1]
401
+ if type1 == type2
402
+ # If the types we're comparing are the same type,
403
+ # then they aren't mutually exclusive
404
+ false
405
+ else
406
+ # Check if these two scopes have _any_ types in common.
407
+ possible_right_types = context.query.possible_types(type1)
408
+ possible_left_types = context.query.possible_types(type2)
409
+ (possible_right_types & possible_left_types).empty?
410
+ end
411
+ end
412
+ else
413
+ true
414
+ end
415
+ end
416
+ end
417
+ end
418
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FieldsWillMergeError < StaticValidation::Error
5
+ attr_reader :field_name
6
+ attr_reader :kind
7
+
8
+ def initialize(kind:, field_name:)
9
+ super(nil)
10
+
11
+ @field_name = field_name
12
+ @kind = kind
13
+ @conflicts = []
14
+ end
15
+
16
+ def message
17
+ "Field '#{field_name}' has #{kind == :argument ? 'an' : 'a'} #{kind} conflict: #{conflicts}?"
18
+ end
19
+
20
+ def path
21
+ []
22
+ end
23
+
24
+ def conflicts
25
+ @conflicts.join(' or ')
26
+ end
27
+
28
+ def add_conflict(node, conflict_str)
29
+ return if nodes.include?(node)
30
+
31
+ @nodes << node
32
+ @conflicts << conflict_str
33
+ end
34
+
35
+ # A hash representation of this Message
36
+ def to_h
37
+ extensions = {
38
+ "code" => code,
39
+ "fieldName" => field_name,
40
+ "conflicts" => conflicts
41
+ }
42
+
43
+ super.merge({
44
+ "extensions" => extensions
45
+ })
46
+ end
47
+
48
+ def code
49
+ "fieldConflict"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ module FragmentNamesAreUnique
5
+
6
+ def initialize(*)
7
+ super
8
+ @fragments_by_name = Hash.new { |h, k| h[k] = [] }
9
+ end
10
+
11
+ def on_fragment_definition(node, parent)
12
+ @fragments_by_name[node.name] << node
13
+ super
14
+ end
15
+
16
+ def on_document(_n, _p)
17
+ super
18
+ @fragments_by_name.each do |name, fragments|
19
+ if fragments.length > 1
20
+ add_error(GraphQL::StaticValidation::FragmentNamesAreUniqueError.new(
21
+ %|Fragment name "#{name}" must be unique|,
22
+ nodes: fragments,
23
+ name: name
24
+ ))
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentNamesAreUniqueError < StaticValidation::Error
5
+ attr_reader :fragment_name
6
+
7
+ def initialize(message, path: nil, nodes: [], name:)
8
+ super(message, path: path, nodes: nodes)
9
+ @fragment_name = name
10
+ end
11
+
12
+ # A hash representation of this Message
13
+ def to_h
14
+ extensions = {
15
+ "code" => code,
16
+ "fragmentName" => fragment_name
17
+ }
18
+
19
+ super.merge({
20
+ "extensions" => extensions
21
+ })
22
+ end
23
+
24
+ def code
25
+ "fragmentNotUnique"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ module FragmentSpreadsArePossible
5
+ def initialize(*)
6
+ super
7
+ @spreads_to_validate = []
8
+ end
9
+
10
+ def on_inline_fragment(node, parent)
11
+ fragment_parent = context.object_types[-2]
12
+ fragment_child = context.object_types.last
13
+ if fragment_child
14
+ validate_fragment_in_scope(fragment_parent, fragment_child, node, context, context.path)
15
+ end
16
+ super
17
+ end
18
+
19
+ def on_fragment_spread(node, parent)
20
+ fragment_parent = context.object_types.last
21
+ @spreads_to_validate << FragmentSpread.new(node: node, parent_type: fragment_parent, path: context.path)
22
+ super
23
+ end
24
+
25
+ def on_document(node, parent)
26
+ super
27
+ @spreads_to_validate.each do |frag_spread|
28
+ frag_node = context.fragments[frag_spread.node.name]
29
+ if frag_node
30
+ fragment_child_name = frag_node.type.name
31
+ fragment_child = context.warden.get_type(fragment_child_name)
32
+ # Might be non-existent type name
33
+ if fragment_child
34
+ validate_fragment_in_scope(frag_spread.parent_type, fragment_child, frag_spread.node, context, frag_spread.path)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def validate_fragment_in_scope(parent_type, child_type, node, context, path)
43
+ if !child_type.kind.fields?
44
+ # It's not a valid fragment type, this error was handled someplace else
45
+ return
46
+ end
47
+ parent_types = context.warden.possible_types(parent_type.unwrap)
48
+ child_types = context.warden.possible_types(child_type.unwrap)
49
+
50
+ if child_types.none? { |c| parent_types.include?(c) }
51
+ name = node.respond_to?(:name) ? " #{node.name}" : ""
52
+ add_error(GraphQL::StaticValidation::FragmentSpreadsArePossibleError.new(
53
+ "Fragment#{name} on #{child_type.graphql_name} can't be spread inside #{parent_type.graphql_name}",
54
+ nodes: node,
55
+ path: path,
56
+ fragment_name: name.empty? ? "unknown" : name,
57
+ type: child_type.graphql_name,
58
+ parent: parent_type.graphql_name
59
+ ))
60
+ end
61
+ end
62
+
63
+ class FragmentSpread
64
+ attr_reader :node, :parent_type, :path
65
+ def initialize(node:, parent_type:, path:)
66
+ @node = node
67
+ @parent_type = parent_type
68
+ @path = path
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class FragmentSpreadsArePossibleError < StaticValidation::Error
5
+ attr_reader :type_name
6
+ attr_reader :fragment_name
7
+ attr_reader :parent_name
8
+
9
+ def initialize(message, path: nil, nodes: [], type:, fragment_name:, parent:)
10
+ super(message, path: path, nodes: nodes)
11
+ @type_name = type
12
+ @fragment_name = fragment_name
13
+ @parent_name = parent
14
+ end
15
+
16
+ # A hash representation of this Message
17
+ def to_h
18
+ extensions = {
19
+ "code" => code,
20
+ "typeName" => type_name,
21
+ "fragmentName" => fragment_name,
22
+ "parentName" => parent_name
23
+ }
24
+
25
+ super.merge({
26
+ "extensions" => extensions
27
+ })
28
+ end
29
+
30
+ def code
31
+ "cannotSpreadFragment"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ module FragmentTypesExist
5
+ def on_fragment_definition(node, _parent)
6
+ if validate_type_exists(node)
7
+ super
8
+ end
9
+ end
10
+
11
+ def on_inline_fragment(node, _parent)
12
+ if validate_type_exists(node)
13
+ super
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def validate_type_exists(fragment_node)
20
+ if !fragment_node.type
21
+ true
22
+ else
23
+ type_name = fragment_node.type.name
24
+ type = context.warden.get_type(type_name)
25
+ if type.nil?
26
+ add_error(GraphQL::StaticValidation::FragmentTypesExistError.new(
27
+ "No such type #{type_name}, so it can't be a fragment condition",
28
+ nodes: fragment_node,
29
+ type: type_name
30
+ ))
31
+ false
32
+ else
33
+ true
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end