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,40 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ # Default rules for {GraphQL::StaticValidation::Validator}
5
+ #
6
+ # Order is important here. Some validators return {GraphQL::Language::Visitor::SKIP}
7
+ # which stops the visit on that node. That way it doesn't try to find fields on types that
8
+ # don't exist, etc.
9
+ ALL_RULES = [
10
+ GraphQL::StaticValidation::NoDefinitionsArePresent,
11
+ GraphQL::StaticValidation::DirectivesAreDefined,
12
+ GraphQL::StaticValidation::DirectivesAreInValidLocations,
13
+ GraphQL::StaticValidation::UniqueDirectivesPerLocation,
14
+ GraphQL::StaticValidation::OperationNamesAreValid,
15
+ GraphQL::StaticValidation::FragmentNamesAreUnique,
16
+ GraphQL::StaticValidation::FragmentsAreFinite,
17
+ GraphQL::StaticValidation::FragmentsAreNamed,
18
+ GraphQL::StaticValidation::FragmentsAreUsed,
19
+ GraphQL::StaticValidation::FragmentTypesExist,
20
+ GraphQL::StaticValidation::FragmentsAreOnCompositeTypes,
21
+ GraphQL::StaticValidation::FragmentSpreadsArePossible,
22
+ GraphQL::StaticValidation::FieldsAreDefinedOnType,
23
+ GraphQL::StaticValidation::FieldsWillMerge,
24
+ GraphQL::StaticValidation::FieldsHaveAppropriateSelections,
25
+ GraphQL::StaticValidation::ArgumentsAreDefined,
26
+ GraphQL::StaticValidation::ArgumentLiteralsAreCompatible,
27
+ GraphQL::StaticValidation::RequiredArgumentsArePresent,
28
+ GraphQL::StaticValidation::RequiredInputObjectAttributesArePresent,
29
+ GraphQL::StaticValidation::ArgumentNamesAreUnique,
30
+ GraphQL::StaticValidation::VariableNamesAreUnique,
31
+ GraphQL::StaticValidation::VariablesAreInputTypes,
32
+ GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped,
33
+ GraphQL::StaticValidation::VariablesAreUsedAndDefined,
34
+ GraphQL::StaticValidation::VariableUsagesAreAllowed,
35
+ GraphQL::StaticValidation::MutationRootExists,
36
+ GraphQL::StaticValidation::SubscriptionRootExists,
37
+ GraphQL::StaticValidation::InputObjectNamesAreUnique,
38
+ ]
39
+ end
40
+ end
@@ -0,0 +1,217 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class BaseVisitor < GraphQL::Language::Visitor
5
+ def initialize(document, context)
6
+ @path = []
7
+ @object_types = []
8
+ @directives = []
9
+ @field_definitions = []
10
+ @argument_definitions = []
11
+ @directive_definitions = []
12
+ @context = context
13
+ @schema = context.schema
14
+ super(document)
15
+ end
16
+
17
+ # This will be overwritten by {InternalRepresentation::Rewrite} if it's included
18
+ def rewrite_document
19
+ nil
20
+ end
21
+
22
+ attr_reader :context
23
+
24
+ # @return [Array<GraphQL::ObjectType>] Types whose scope we've entered
25
+ attr_reader :object_types
26
+
27
+ # @return [Array<String>] The nesting of the current position in the AST
28
+ def path
29
+ @path.dup
30
+ end
31
+
32
+ # Build a class to visit the AST and perform validation,
33
+ # or use a pre-built class if rules is `ALL_RULES` or empty.
34
+ # @param rules [Array<Module, Class>]
35
+ # @param rewrite [Boolean] if `false`, don't include rewrite
36
+ # @return [Class] A class for validating `rules` during visitation
37
+ def self.including_rules(rules, rewrite: true)
38
+ if rules.empty?
39
+ if rewrite
40
+ NoValidateVisitor
41
+ else
42
+ # It's not doing _anything?!?_
43
+ BaseVisitor
44
+ end
45
+ elsif rules == ALL_RULES
46
+ if rewrite
47
+ DefaultVisitor
48
+ else
49
+ InterpreterVisitor
50
+ end
51
+ else
52
+ visitor_class = Class.new(self) do
53
+ include(GraphQL::StaticValidation::DefinitionDependencies)
54
+ end
55
+
56
+ rules.reverse_each do |r|
57
+ # If it's a class, it gets attached later.
58
+ if !r.is_a?(Class)
59
+ visitor_class.include(r)
60
+ end
61
+ end
62
+
63
+ if rewrite
64
+ visitor_class.include(GraphQL::InternalRepresentation::Rewrite)
65
+ end
66
+ visitor_class.include(ContextMethods)
67
+ visitor_class
68
+ end
69
+ end
70
+
71
+ module ContextMethods
72
+ def on_operation_definition(node, parent)
73
+ object_type = @schema.root_type_for_operation(node.operation_type)
74
+ push_type(object_type)
75
+ @path.push("#{node.operation_type}#{node.name ? " #{node.name}" : ""}")
76
+ super
77
+ @object_types.pop
78
+ @path.pop
79
+ end
80
+
81
+ def on_fragment_definition(node, parent)
82
+ on_fragment_with_type(node) do
83
+ @path.push("fragment #{node.name}")
84
+ super
85
+ end
86
+ end
87
+
88
+ def on_inline_fragment(node, parent)
89
+ on_fragment_with_type(node) do
90
+ @path.push("...#{node.type ? " on #{node.type.to_query_string}" : ""}")
91
+ super
92
+ end
93
+ end
94
+
95
+ def on_field(node, parent)
96
+ parent_type = @object_types.last
97
+ field_definition = @schema.get_field(parent_type, node.name, @context.query.context)
98
+ @field_definitions.push(field_definition)
99
+ if !field_definition.nil?
100
+ next_object_type = field_definition.type.unwrap
101
+ push_type(next_object_type)
102
+ else
103
+ push_type(nil)
104
+ end
105
+ @path.push(node.alias || node.name)
106
+ super
107
+ @field_definitions.pop
108
+ @object_types.pop
109
+ @path.pop
110
+ end
111
+
112
+ def on_directive(node, parent)
113
+ directive_defn = @schema.directives[node.name]
114
+ @directive_definitions.push(directive_defn)
115
+ super
116
+ @directive_definitions.pop
117
+ end
118
+
119
+ def on_argument(node, parent)
120
+ argument_defn = if (arg = @argument_definitions.last)
121
+ arg_type = arg.type.unwrap
122
+ if arg_type.kind.input_object?
123
+ @context.warden.get_argument(arg_type, node.name)
124
+ else
125
+ nil
126
+ end
127
+ elsif (directive_defn = @directive_definitions.last)
128
+ @context.warden.get_argument(directive_defn, node.name)
129
+ elsif (field_defn = @field_definitions.last)
130
+ @context.warden.get_argument(field_defn, node.name)
131
+ else
132
+ nil
133
+ end
134
+
135
+ @argument_definitions.push(argument_defn)
136
+ @path.push(node.name)
137
+ super
138
+ @argument_definitions.pop
139
+ @path.pop
140
+ end
141
+
142
+ def on_fragment_spread(node, parent)
143
+ @path.push("... #{node.name}")
144
+ super
145
+ @path.pop
146
+ end
147
+
148
+ def on_input_object(node, parent)
149
+ arg_defn = @argument_definitions.last
150
+ if arg_defn && arg_defn.type.list?
151
+ @path.push(parent.children.index(node))
152
+ super
153
+ @path.pop
154
+ else
155
+ super
156
+ end
157
+ end
158
+
159
+ # @return [GraphQL::BaseType] The current object type
160
+ def type_definition
161
+ @object_types.last
162
+ end
163
+
164
+ # @return [GraphQL::BaseType] The type which the current type came from
165
+ def parent_type_definition
166
+ @object_types[-2]
167
+ end
168
+
169
+ # @return [GraphQL::Field, nil] The most-recently-entered GraphQL::Field, if currently inside one
170
+ def field_definition
171
+ @field_definitions.last
172
+ end
173
+
174
+ # @return [GraphQL::Directive, nil] The most-recently-entered GraphQL::Directive, if currently inside one
175
+ def directive_definition
176
+ @directive_definitions.last
177
+ end
178
+
179
+ # @return [GraphQL::Argument, nil] The most-recently-entered GraphQL::Argument, if currently inside one
180
+ def argument_definition
181
+ # Don't get the _last_ one because that's the current one.
182
+ # Get the second-to-last one, which is the parent of the current one.
183
+ @argument_definitions[-2]
184
+ end
185
+
186
+ private
187
+
188
+ def on_fragment_with_type(node)
189
+ object_type = if node.type
190
+ @context.warden.get_type(node.type.name)
191
+ else
192
+ @object_types.last
193
+ end
194
+ push_type(object_type)
195
+ yield(node)
196
+ @object_types.pop
197
+ @path.pop
198
+ end
199
+
200
+ def push_type(t)
201
+ @object_types.push(t)
202
+ end
203
+ end
204
+
205
+ private
206
+
207
+ def add_error(error, path: nil)
208
+ if @context.too_many_errors?
209
+ throw :too_many_validation_errors
210
+ end
211
+ error.path ||= (path || @path.dup)
212
+ context.errors << error
213
+ end
214
+
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class DefaultVisitor < BaseVisitor
5
+ include(GraphQL::StaticValidation::DefinitionDependencies)
6
+
7
+ StaticValidation::ALL_RULES.reverse_each do |r|
8
+ include(r)
9
+ end
10
+
11
+ include(GraphQL::InternalRepresentation::Rewrite)
12
+ include(ContextMethods)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,198 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ # Track fragment dependencies for operations
5
+ # and expose the fragment definitions which
6
+ # are used by a given operation
7
+ module DefinitionDependencies
8
+ attr_reader :dependencies
9
+
10
+ def initialize(*)
11
+ super
12
+ @defdep_node_paths = {}
13
+
14
+ # { name => [node, ...] } pairs for fragments (although duplicate-named fragments are _invalid_, they are _possible_)
15
+ @defdep_fragment_definitions = Hash.new{ |h, k| h[k] = [] }
16
+
17
+ # This tracks dependencies from fragment to Node where it was used
18
+ # { fragment_definition_name => [dependent_node, dependent_node]}
19
+ @defdep_dependent_definitions = Hash.new { |h, k| h[k] = Set.new }
20
+
21
+ # First-level usages of spreads within definitions
22
+ # (When a key has an empty list as its value,
23
+ # we can resolve that key's dependents)
24
+ # { definition_node => [node, node ...] }
25
+ @defdep_immediate_dependencies = Hash.new { |h, k| h[k] = Set.new }
26
+
27
+ # When we encounter a spread,
28
+ # this node is the one who depends on it
29
+ @defdep_current_parent = nil
30
+ end
31
+
32
+ def on_document(node, parent)
33
+ node.definitions.each do |definition|
34
+ if definition.is_a? GraphQL::Language::Nodes::FragmentDefinition
35
+ @defdep_fragment_definitions[definition.name] << definition
36
+ end
37
+ end
38
+ super
39
+ @dependencies = dependency_map { |defn, spreads, frag|
40
+ context.on_dependency_resolve_handlers.each { |h| h.call(defn, spreads, frag) }
41
+ }
42
+ end
43
+
44
+ def on_operation_definition(node, prev_node)
45
+ @defdep_node_paths[node.name] = NodeWithPath.new(node, context.path)
46
+ @defdep_current_parent = node
47
+ super
48
+ @defdep_current_parent = nil
49
+ end
50
+
51
+ def on_fragment_definition(node, parent)
52
+ @defdep_node_paths[node] = NodeWithPath.new(node, context.path)
53
+ @defdep_current_parent = node
54
+ super
55
+ @defdep_current_parent = nil
56
+ end
57
+
58
+ def on_fragment_spread(node, parent)
59
+ @defdep_node_paths[node] = NodeWithPath.new(node, context.path)
60
+
61
+ # Track both sides of the dependency
62
+ @defdep_dependent_definitions[node.name] << @defdep_current_parent
63
+ @defdep_immediate_dependencies[@defdep_current_parent] << node
64
+ super
65
+ end
66
+
67
+ # A map of operation definitions to an array of that operation's dependencies
68
+ # @return [DependencyMap]
69
+ def dependency_map(&block)
70
+ @dependency_map ||= resolve_dependencies(&block)
71
+ end
72
+
73
+ # Map definition AST nodes to the definition AST nodes they depend on.
74
+ # Expose circular dependencies.
75
+ class DependencyMap
76
+ # @return [Array<GraphQL::Language::Nodes::FragmentDefinition>]
77
+ attr_reader :cyclical_definitions
78
+
79
+ # @return [Hash<Node, Array<GraphQL::Language::Nodes::FragmentSpread>>]
80
+ attr_reader :unmet_dependencies
81
+
82
+ # @return [Array<GraphQL::Language::Nodes::FragmentDefinition>]
83
+ attr_reader :unused_dependencies
84
+
85
+ def initialize
86
+ @dependencies = Hash.new { |h, k| h[k] = [] }
87
+ @cyclical_definitions = []
88
+ @unmet_dependencies = Hash.new { |h, k| h[k] = [] }
89
+ @unused_dependencies = []
90
+ end
91
+
92
+ # @return [Array<GraphQL::Language::Nodes::AbstractNode>] dependencies for `definition_node`
93
+ def [](definition_node)
94
+ @dependencies[definition_node]
95
+ end
96
+ end
97
+
98
+ class NodeWithPath
99
+ extend Forwardable
100
+ attr_reader :node, :path
101
+ def initialize(node, path)
102
+ @node = node
103
+ @path = path
104
+ end
105
+
106
+ def_delegators :@node, :name, :eql?, :hash
107
+ end
108
+
109
+ private
110
+
111
+ # Return a hash of { node => [node, node ... ]} pairs
112
+ # Keys are top-level definitions
113
+ # Values are arrays of flattened dependencies
114
+ def resolve_dependencies
115
+ dependency_map = DependencyMap.new
116
+ # Don't allow the loop to run more times
117
+ # than the number of fragments in the document
118
+ max_loops = 0
119
+ @defdep_fragment_definitions.each_value do |v|
120
+ max_loops += v.size
121
+ end
122
+
123
+ loops = 0
124
+
125
+ # Instead of tracking independent fragments _as you visit_,
126
+ # determine them at the end. This way, we can treat fragments with the
127
+ # same name as if they were the same name. If _any_ of the fragments
128
+ # with that name has a dependency, we record it.
129
+ independent_fragment_nodes = @defdep_fragment_definitions.values.flatten - @defdep_immediate_dependencies.keys
130
+
131
+ while fragment_node = independent_fragment_nodes.pop
132
+ loops += 1
133
+ if loops > max_loops
134
+ raise("Resolution loops exceeded the number of definitions; infinite loop detected. (Max: #{max_loops}, Current: #{loops})")
135
+ end
136
+ # Since it's independent, let's remove it from here.
137
+ # That way, we can use the remainder to identify cycles
138
+ @defdep_immediate_dependencies.delete(fragment_node)
139
+ fragment_usages = @defdep_dependent_definitions[fragment_node.name]
140
+ if fragment_usages.empty?
141
+ # If we didn't record any usages during the visit,
142
+ # then this fragment is unused.
143
+ dependency_map.unused_dependencies << @defdep_node_paths[fragment_node]
144
+ else
145
+ fragment_usages.each do |definition_node|
146
+ # Register the dependency AND second-order dependencies
147
+ dependency_map[definition_node] << fragment_node
148
+ dependency_map[definition_node].concat(dependency_map[fragment_node])
149
+ # Since we've registered it, remove it from our to-do list
150
+ deps = @defdep_immediate_dependencies[definition_node]
151
+ # Can't find a way to _just_ delete from `deps` and return the deleted entries
152
+ removed, remaining = deps.partition { |spread| spread.name == fragment_node.name }
153
+ @defdep_immediate_dependencies[definition_node] = remaining
154
+ if block_given?
155
+ yield(definition_node, removed, fragment_node)
156
+ end
157
+ if remaining.empty? &&
158
+ definition_node.is_a?(GraphQL::Language::Nodes::FragmentDefinition) &&
159
+ definition_node.name != fragment_node.name
160
+ # If all of this definition's dependencies have
161
+ # been resolved, we can now resolve its
162
+ # own dependents.
163
+ #
164
+ # But, it's possible to have a duplicate-named fragment here.
165
+ # Skip it in that case
166
+ independent_fragment_nodes << definition_node
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ # If any dependencies were _unmet_
173
+ # (eg, spreads with no corresponding definition)
174
+ # then they're still in there
175
+ @defdep_immediate_dependencies.each do |defn_node, deps|
176
+ deps.each do |spread|
177
+ if !@defdep_fragment_definitions.key?(spread.name)
178
+ dependency_map.unmet_dependencies[@defdep_node_paths[defn_node]] << @defdep_node_paths[spread]
179
+ deps.delete(spread)
180
+ end
181
+ end
182
+ if deps.empty?
183
+ @defdep_immediate_dependencies.delete(defn_node)
184
+ end
185
+ end
186
+
187
+ # Anything left in @immediate_dependencies is cyclical
188
+ cyclical_nodes = @defdep_immediate_dependencies.keys.map { |n| @defdep_node_paths[n] }
189
+ # @immediate_dependencies also includes operation names, but we don't care about
190
+ # those. They became nil when we looked them up on `@fragment_definitions`, so remove them.
191
+ cyclical_nodes.compact!
192
+ dependency_map.cyclical_definitions.concat(cyclical_nodes)
193
+
194
+ dependency_map
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ # Generates GraphQL-compliant validation message.
5
+ class Error
6
+ # Convenience for validators
7
+ module ErrorHelper
8
+ # Error `error_message` is located at `node`
9
+ def error(error_message, nodes, context: nil, path: nil, extensions: {})
10
+ path ||= context.path
11
+ nodes = Array(nodes)
12
+ GraphQL::StaticValidation::Error.new(error_message, nodes: nodes, path: path)
13
+ end
14
+ end
15
+
16
+ attr_reader :message
17
+ attr_accessor :path
18
+
19
+ def initialize(message, path: nil, nodes: [])
20
+ @message = message
21
+ @nodes = Array(nodes)
22
+ @path = path
23
+ end
24
+
25
+ # A hash representation of this Message
26
+ def to_h
27
+ {
28
+ "message" => message,
29
+ "locations" => locations
30
+ }.tap { |h| h["path"] = path unless path.nil? }
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :nodes
36
+
37
+ def locations
38
+ nodes.map do |node|
39
+ h = {"line" => node.line, "column" => node.col}
40
+ h["filename"] = node.filename if node.filename
41
+ h
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class InterpreterVisitor < BaseVisitor
5
+ include(GraphQL::StaticValidation::DefinitionDependencies)
6
+
7
+ StaticValidation::ALL_RULES.reverse_each do |r|
8
+ include(r)
9
+ end
10
+
11
+ include(ContextMethods)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ # Test whether `ast_value` is a valid input for `type`
5
+ class LiteralValidator
6
+ def initialize(context:)
7
+ @context = context
8
+ @warden = context.warden
9
+ @invalid_response = GraphQL::Query::InputValidationResult.new(valid: false, problems: [])
10
+ @valid_response = GraphQL::Query::InputValidationResult.new(valid: true, problems: [])
11
+ end
12
+
13
+ def validate(ast_value, type)
14
+ catch(:invalid) do
15
+ recursively_validate(ast_value, type)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def recursively_validate(ast_value, type)
22
+ if type.nil?
23
+ # this means we're an undefined argument, see #present_input_field_values_are_valid
24
+ maybe_raise_if_invalid(ast_value) do
25
+ @invalid_response
26
+ end
27
+ elsif ast_value.is_a?(GraphQL::Language::Nodes::NullValue)
28
+ maybe_raise_if_invalid(ast_value) do
29
+ type.kind.non_null? ? @invalid_response : @valid_response
30
+ end
31
+ elsif type.kind.non_null?
32
+ maybe_raise_if_invalid(ast_value) do
33
+ ast_value.nil? ?
34
+ @invalid_response :
35
+ recursively_validate(ast_value, type.of_type)
36
+ end
37
+ elsif type.kind.list?
38
+ item_type = type.of_type
39
+ results = ensure_array(ast_value).map { |val| recursively_validate(val, item_type) }
40
+ merge_results(results)
41
+ elsif ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
42
+ @valid_response
43
+ elsif type.kind.scalar? && constant_scalar?(ast_value)
44
+ maybe_raise_if_invalid(ast_value) do
45
+ type.validate_input(ast_value, @context)
46
+ end
47
+ elsif type.kind.enum?
48
+ maybe_raise_if_invalid(ast_value) do
49
+ if ast_value.is_a?(GraphQL::Language::Nodes::Enum)
50
+ type.validate_input(ast_value.name, @context)
51
+ else
52
+ # if our ast_value isn't an Enum it's going to be invalid so return false
53
+ @invalid_response
54
+ end
55
+ end
56
+ elsif type.kind.input_object? && ast_value.is_a?(GraphQL::Language::Nodes::InputObject)
57
+ maybe_raise_if_invalid(ast_value) do
58
+ merge_results([
59
+ required_input_fields_are_present(type, ast_value),
60
+ present_input_field_values_are_valid(type, ast_value)
61
+ ])
62
+ end
63
+ else
64
+ maybe_raise_if_invalid(ast_value) do
65
+ @invalid_response
66
+ end
67
+ end
68
+ end
69
+
70
+ # When `error_bubbling` is false, we want to bail on the first failure that we find.
71
+ # Use `throw` to escape the current call stack, returning the invalid response.
72
+ def maybe_raise_if_invalid(ast_value)
73
+ ret = yield
74
+ if !@context.schema.error_bubbling && !ret.valid?
75
+ throw(:invalid, ret)
76
+ else
77
+ ret
78
+ end
79
+ end
80
+
81
+ # The GraphQL grammar supports variables embedded within scalars but graphql.js
82
+ # doesn't support it so we won't either for simplicity
83
+ def constant_scalar?(ast_value)
84
+ if ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
85
+ false
86
+ elsif ast_value.is_a?(Array)
87
+ ast_value.all? { |element| constant_scalar?(element) }
88
+ elsif ast_value.is_a?(GraphQL::Language::Nodes::InputObject)
89
+ ast_value.arguments.all? { |arg| constant_scalar?(arg.value) }
90
+ else
91
+ true
92
+ end
93
+ end
94
+
95
+ def required_input_fields_are_present(type, ast_node)
96
+ # TODO - would be nice to use these to create an error message so the caller knows
97
+ # that required fields are missing
98
+ required_field_names = @warden.arguments(type)
99
+ .select { |argument| argument.type.kind.non_null? && @warden.get_argument(type, argument.name) }
100
+ .map(&:name)
101
+
102
+ present_field_names = ast_node.arguments.map(&:name)
103
+ missing_required_field_names = required_field_names - present_field_names
104
+ if @context.schema.error_bubbling
105
+ missing_required_field_names.empty? ? @valid_response : @invalid_response
106
+ else
107
+ results = missing_required_field_names.map do |name|
108
+ arg_type = @warden.get_argument(type, name).type
109
+ recursively_validate(GraphQL::Language::Nodes::NullValue.new(name: name), arg_type)
110
+ end
111
+ merge_results(results)
112
+ end
113
+ end
114
+
115
+ def present_input_field_values_are_valid(type, ast_node)
116
+ results = ast_node.arguments.map do |value|
117
+ field = @warden.get_argument(type, value.name)
118
+ # we want to call validate on an argument even if it's an invalid one
119
+ # so that our raise exception is on it instead of the entire InputObject
120
+ field_type = field && field.type
121
+ recursively_validate(value.value, field_type)
122
+ end
123
+ merge_results(results)
124
+ end
125
+
126
+ def ensure_array(value)
127
+ value.is_a?(Array) ? value : [value]
128
+ end
129
+
130
+ def merge_results(results_list)
131
+ merged_result = Query::InputValidationResult.new
132
+ results_list.each do |inner_result|
133
+ merged_result.merge_result!([], inner_result)
134
+ end
135
+ merged_result
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ module GraphQL
3
+ module StaticValidation
4
+ class NoValidateVisitor < StaticValidation::BaseVisitor
5
+ include(GraphQL::InternalRepresentation::Rewrite)
6
+ include(GraphQL::StaticValidation::DefinitionDependencies)
7
+ include(ContextMethods)
8
+ end
9
+ end
10
+ end